codemode

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

README

CodeMode

CodeMode is a Go library for building MCP servers where the agent writes code instead of chaining tool calls. You register plain Go functions as capabilities. An agent discovers them, then submits a small Starlark program that calls several capabilities, filters and combines their results in the program, and returns one value.

Every CodeMode server exposes the same three MCP tools through the official MCP Go SDK:

  • search_api — ranked discovery over your capability names, summaries, and search terms
  • describe_api — exact call signatures and result shapes, generated from your Go types
  • execute — run one Starlark program against those capabilities

Compared to a conventional MCP server with one tool per function:

  • Loops, filtering, and aggregation happen inside the program, so multi-step work takes one round trip and intermediate data never enters the model's context window.
  • The schemas the agent sees are derived from your registered Go types, so they cannot drift from handler behavior.
  • Capabilities can be disabled per deployment by stable ID without code changes.
  • Every capability call is authorized before dispatch, fail-closed, with the arguments the handler will receive. The optional authz/rego adapter evaluates OPA/Rego policy in-process.
  • Each program runs in a fresh worker process under execution budgets, and only the program's final value is returned to the caller.

Install

go get github.com/meigma/codemode@v0.2.0

The module requires Go 1.26.6.

Get started

func main() {
	// Serve worker mode when this binary is re-executed for a program run.
	// This must be the first statement of main.
	codemode.ServeWorkerAndExit()

	// AllowAll is an explicit choice; CodeMode has no default authorizer.
	builder := codemode.New(codemode.Options{Authorizer: authz.AllowAll()})

	// A capability is a plain typed Go function. The schema agents see is
	// generated from lookupInput and lookupOutput.
	codemode.Register(builder, codemode.Capability[lookupInput, lookupOutput]{
		Name:    "records.lookup",
		Summary: "Look up one record by key.",
		Handler: lookup,
	})

	server, err := builder.Build()
	if err != nil {
		log.Fatal(err)
	}

	// StaticSubject suits a single-user stdio server; multi-user hosts
	// resolve each authenticated request with ContextSubject.
	srv, err := mcpserver.New(server, mcpserver.StaticSubject(authz.Subject{ID: "local"}), mcpserver.Options{})
	if err != nil {
		log.Fatal(err)
	}
	if err := srv.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
		log.Fatal(err)
	}
}

For the full walk-through — the input and output types, building the binary, and adding it to an agent — follow Build your first CodeMode server. Shorter compile-checked examples: example_test.go and mcpserver/example_test.go.

Documentation

How this differs from Cloudflare's Code Mode

Cloudflare's Code Mode and CodeMode share a thesis: models are better at writing code than at emitting tool calls. They apply it on opposite sides of the protocol.

Cloudflare's Code Mode is agent-side. Their Agents SDK converts the tool schemas of the MCP servers an agent already uses into a TypeScript API; the model writes TypeScript that runs in a V8 isolate on the Workers platform, and each call proxies back to the original servers.

CodeMode is server-side. You author the server itself: capabilities are native typed Go functions, not wrapped remote tools, and the server runs the agent's program in a local worker process. Because code execution is part of the server's own contract, any MCP client gets one-round-trip composition without a special agent framework or hosting platform. The server also enforces its own policy: every capability call is authorized before it dispatches, and a deployment can disable capabilities it does not want to expose.

Security boundary

Each execute request runs Starlark in a fresh worker process that CodeMode can kill on deadline or cancellation. Arguments are bound and canonicalized before authorization, authorization completes before handler dispatch, and the trusted subject comes only from host-owned context — never from tool arguments, program source, or MCP _meta. Execution budgets bound source size, steps, time, native calls, and value sizes; they are not operating-system CPU or memory quotas, and CodeMode cannot forcibly stop a dispatched Go handler. The security model defines the full boundary; see SECURITY.md for vulnerability reporting.

Contributing

See CONTRIBUTING.md for the documentation layout, repository checks, and pull request expectations.

License

CodeMode is licensed under the Apache License 2.0.

Documentation

Overview

Package codemode builds immutable catalogs of typed Go capabilities and executes bounded, authorized Starlark programs against them.

Host wiring

A final binary must enter worker mode before flag parsing or ordinary host setup:

func main() {
	codemode.ServeWorkerAndExit()

	// Parse flags and construct credentials, clients, authorizers, handlers,
	// the CodeMode Server, and the host transport here.
}

A test binary that calls Builder.Build must do the same:

func TestMain(m *testing.M) {
	codemode.ServeWorkerAndExit()
	os.Exit(m.Run())
}

ServeWorkerAndExit must be the first statement of main and TestMain. A library that embeds CodeMode cannot satisfy this requirement for an application it does not own; it must tell downstream users to install the call in their final binary and in every test binary that calls Builder.Build.

Example (RegisterAndExecute)

Example_registerAndExecute registers one typed capability and prints main's final value.

authz.AllowAll is deliberate in this sample. Production hosts normally supply an Authorizer that inspects the trusted subject and canonical arguments.

package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/meigma/codemode"
	"github.com/meigma/codemode/authz"
)

func main() {
	// lookupInput is the records.lookup argument contract.
	type lookupInput struct {
		// Key is the required record identifier.
		Key string `json:"key"`

		// Limit is the optional result bound.
		Limit *int64 `json:"limit,omitempty"`
	}

	// lookupOutput is the records.lookup handler result.
	type lookupOutput struct {
		// Key is the looked-up record identifier.
		Key string `json:"key"`

		// Count is the resolved optional limit, or zero when omitted.
		Count int64 `json:"count"`
	}

	builder := codemode.New(codemode.Options{Authorizer: authz.AllowAll()})
	codemode.Register(builder, codemode.Capability[lookupInput, lookupOutput]{
		Name:    "records.lookup",
		Summary: "Look up one record by key.",
		Handler: func(_ context.Context, _ authz.Subject, input lookupInput) (lookupOutput, error) {
			count := int64(0)
			if input.Limit != nil {
				count = *input.Limit
			}
			return lookupOutput{Key: input.Key, Count: count}, nil
		},
	})

	server, err := builder.Build()
	if err != nil {
		panic(err)
	}

	result, err := server.Execute(context.Background(), authz.Subject{ID: "example-user"}, `
print("discarded")
def main():
    return records.lookup(key="alpha", limit=2)
`)
	if err != nil {
		panic(err)
	}

	encoded, err := json.Marshal(result)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(encoded))
}
Output:
{"count":2,"key":"alpha"}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidRegistration classifies invalid capability registration, limits, or server construction.
	ErrInvalidRegistration = errors.New("invalid registration")

	// ErrUnauthenticated classifies failure to resolve a trusted invocation subject.
	ErrUnauthenticated = errors.New("unauthenticated")

	// ErrNotFound classifies an unavailable or disabled capability.
	ErrNotFound = errors.New("capability not found")

	// ErrInvalidProgram classifies invalid Starlark source or entrypoint behavior.
	ErrInvalidProgram = errors.New("invalid program")

	// ErrInvalidArguments classifies capability arguments rejected before authorization.
	ErrInvalidArguments = errors.New("invalid capability arguments")

	// ErrPermissionDenied classifies a recognized authorization denial.
	ErrPermissionDenied = errors.New("permission denied")

	// ErrPolicyFailure classifies an authorization evaluation failure.
	ErrPolicyFailure = errors.New("authorization policy failure")

	// ErrResourceLimit classifies a configured execution or conversion limit.
	ErrResourceLimit = errors.New("resource limit exceeded")

	// ErrCapabilityFailure classifies a native capability handler failure.
	ErrCapabilityFailure = errors.New("capability failed")

	// ErrInternal classifies an unexpected framework failure.
	ErrInternal = errors.New("internal failure")
)

Functions

func IsWorker

func IsWorker() bool

IsWorker reports whether the current process was re-executed as a CodeMode worker.

Most hosts should call ServeWorkerAndExit instead. A host that uses IsWorker directly must still serve worker mode before flag parsing or constructing credentials, clients, authorizers, handlers, or a Server, and must not fall through into ordinary host wiring.

func Register

func Register[Input, Output any](builder *Builder, capability Capability[Input, Output])

Register compiles and retains one typed capability without erasing its binding contract first.

Capability-specific failures are accumulated and returned together by Build. A name whose first dotted segment collides with a reserved Starlark universe root, including standard builtins, sum, json, and math, is recorded as an invalid registration; nested leaves such as stats.sum remain legal. Register panics when builder is nil or already closed because no future Build call can report those lifecycle violations.

func ServeWorkerAndExit

func ServeWorkerAndExit()

ServeWorkerAndExit serves one CodeMode probe or execution request and terminates the process when the current process is a CodeMode worker. It returns immediately in an ordinary host process.

Call ServeWorkerAndExit as the first statement of main, and of TestMain in every test binary that calls Builder.Build. The call must precede flag parsing and construction of credentials, service clients, authorizers, handlers, a Server, or a transport.

In worker mode, ServeWorkerAndExit exits with status 0 after a successful exchange and status 1 after an internal worker or protocol failure. It does not return an error and writes no diagnostic. Standard output is reserved for protocol frames. In worker mode this function calls os.Exit, so deferred functions do not run.

Types

type AgentError added in v0.2.1

type AgentError struct {
	// Message is the handler-authored, agent-facing failure explanation.
	Message string
}

AgentError carries a message the handler author has chosen to expose to the agent.

Return it directly or wrap it using %w. Only Message is exposed, never surrounding error text. CodeMode replaces non-printable runes with spaces and truncates the message to 256 UTF-8 bytes, including a trailing "..." when truncated. Empty messages leave the capability failure bare. The host must not put secrets or other sensitive data in Message.

func (*AgentError) Error added in v0.2.1

func (err *AgentError) Error() string

Error returns the handler-authored message before sanitization.

type Builder

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

Builder collects capability registrations for one immutable Server.

A Builder is single-threaded and one-shot. Its first Build call closes registration even when validation fails. Construct another Builder to change configuration or capability visibility.

func New

func New(options Options) *Builder

New creates a mutable one-shot Builder and copies caller-owned option slices.

The final binary must call ServeWorkerAndExit as the first statement of main before it calls New or performs ordinary host setup. Test binaries that call Build must make the same call as the first statement of TestMain.

func (*Builder) Build

func (builder *Builder) Build() (*Server, error)

Build closes the Builder and returns an immutable concurrency-safe Server after full validation and a same-executable worker probe.

Build allows up to five seconds for the probe exchange, then kills and reaps the probe child; operating-system spawn and kill/reap overhead can extend the call beyond that exchange deadline. Build has no context and the probe deadline is not configurable.

The final binary must call ServeWorkerAndExit as the first statement of main, and a test binary that calls Build must do the same in TestMain. The probe detects an absent or nonfunctional worker entry, but it cannot detect ordinary host work that completes silently before ServeWorkerAndExit is called.

type Capability

type Capability[Input, Output any] struct {
	// ID is the stable identity used by deployment filtering and authorization
	// policy. An empty ID defaults to Name. Set ID explicitly before writing
	// policy or deployment filters against this capability.
	ID CapabilityID

	// Name is the dotted Starlark name exposed to programs and discovery.
	// The first segment must not collide with a reserved Starlark universe root.
	Name CapabilityName

	// Summary is a compact description used by capability search.
	Summary string

	// Description explains the capability behavior for exact description
	// requests. An empty Description defaults to Summary.
	Description string

	// SearchTerms contains alternative task vocabulary used only for discovery.
	// Terms are not callable aliases and are not accepted by Describe or Execute.
	// They are not returned in search results, but callers can infer indexed
	// vocabulary by probing. Do not put secrets, policy facts, credentials,
	// tenant identifiers, or sensitive examples in search terms.
	SearchTerms []string

	// Handler executes the capability after binding and authorization succeed.
	Handler Handler[Input, Output]
}

Capability describes one typed native operation available to CodeMode.

type CapabilityID

type CapabilityID string

CapabilityID is a stable deployment and authorization identity for a capability.

type CapabilityName

type CapabilityName string

CapabilityName is the dotted name exposed to Starlark programs and model-facing discovery.

type Description

type Description = catalog.Description

Description is one exact enabled-capability description and supported binding shape.

type Handler

type Handler[Input, Output any] func(context.Context, authz.Subject, Input) (Output, error)

Handler executes one capability with trusted subject identity and typed input.

type Limits

type Limits struct {
	// MaxSourceBytes is the maximum accepted Starlark source size in bytes.
	MaxSourceBytes int

	// MaxExecutionSteps is the maximum number of Starlark bytecode steps.
	MaxExecutionSteps uint64

	// MaxExecutionTime is the maximum elapsed execution budget. The budget starts
	// before waiting for a worker slot and covers spawn, protocol exchange,
	// Starlark execution, and parent dispatch. Killing and reaping can add
	// operating-system overhead.
	MaxExecutionTime time.Duration

	// MaxNativeCalls is the maximum number of attempted native capability calls.
	MaxNativeCalls uint64

	// MaxValueDepth is the maximum nesting depth of any JSON-shaped value crossing
	// the worker boundary, including arguments, native results, and the final value.
	MaxValueDepth int

	// MaxValueBytes is the maximum encoded size of any JSON-shaped value crossing
	// the worker boundary, including arguments, native results, and the final value.
	// Size is measured by CodeMode's type-preserving JSON value encoder.
	MaxValueBytes int

	// MaxIntermediateValueBytes is the maximum cumulative encoded size of
	// successful parent-to-child native-result value bodies in one Execute
	// call. Size is measured by CodeMode's type-preserving JSON value encoder
	// and excludes frame envelopes, native-call arguments, failed handlers,
	// and the final program value. The budget is independent of MaxValueBytes.
	MaxIntermediateValueBytes int

	// MaxSearchQueryBytes is the maximum capability-search query size in bytes.
	MaxSearchQueryBytes int

	// MaxSearchResults is the maximum number of capability-search results.
	MaxSearchResults int

	// MaxConcurrentExecutions is the maximum number of concurrent spawn attempts
	// and live execution-worker children. Waiting for a slot consumes
	// MaxExecutionTime and remains cancelable through the request context.
	MaxConcurrentExecutions int
}

Limits bounds one execution and the model-facing catalog search surface.

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits returns positive development defaults for every supported budget.

func (Limits) Validate

func (limits Limits) Validate() error

Validate rejects non-positive limits; Build replaces zero-valued fields with bounded defaults before validation.

type Options

type Options struct {
	// Authorizer decides whether each validated native capability call may dispatch.
	Authorizer authz.Authorizer

	// DisabledCapabilities lists stable capability IDs removed from every live server surface.
	DisabledCapabilities []CapabilityID

	// Limits contains execution, conversion, and discovery budgets. Build
	// replaces each zero-valued field with the corresponding DefaultLimits value.
	Limits Limits
}

Options configures one immutable CodeMode server build.

type Program

type Program string

Program is one bounded Starlark source program executed by a Server.

type SearchResponse

type SearchResponse = catalog.SearchResponse

SearchResponse is one bounded ranked discovery result set.

type SearchResult

type SearchResult = catalog.SearchResult

SearchResult is one compact enabled-capability discovery record.

type Server

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

Server is an immutable, concurrency-safe capability catalog and Starlark execution service.

Every Execute call runs Starlark in a fresh worker process and owns fresh budgets. An elapsed deadline kills and reaps that worker. Registered Authorizer and Handler implementations run in the parent, must honor their context, return promptly, and be safe for the caller's concurrency.

func (*Server) Describe

func (server *Server) Describe(name CapabilityName) (Description, error)

Describe returns one exact enabled capability description or ErrNotFound.

func (*Server) Execute

func (server *Server) Execute(ctx context.Context, subject authz.Subject, program Program) (any, error)

Execute runs one bounded program for a trusted authenticated subject and returns only main's final value.

Execute re-executes the current binary for each call. The elapsed budget includes worker-slot waiting, process startup, protocol exchange, Starlark execution, and parent dispatch. Deadline or request cancellation kills and reaps the child, but CodeMode cannot forcibly stop parent-side Authorizer or Handler code that ignores its context.

func (*Server) Search

func (server *Server) Search(query string) (SearchResponse, error)

Search returns a bounded relevance-ranked scan of enabled capabilities.

Directories

Path Synopsis
Package authz defines the trusted authorization boundary for native capability calls.
Package authz defines the trusted authorization boundary for native capability calls.
mocks
Package mocks contains generated test doubles for authorization ports.
Package mocks contains generated test doubles for authorization ports.
rego
Package rego implements authz.Authorizer with one prepared in-process Rego decision.
Package rego implements authz.Authorizer with one prepared in-process Rego decision.
internal
binding
Package binding compiles restricted Go input and output types into immutable conversion plans and owns process-neutral value conversion.
Package binding compiles restricted Go input and output types into immutable conversion plans and owns process-neutral value conversion.
catalog
Package catalog validates, filters, and compiles immutable native capability registrations.
Package catalog validates, filters, and compiles immutable native capability registrations.
execution
Package execution runs one restricted, bounded Starlark program at a time.
Package execution runs one restricted, bounded Starlark program at a time.
universe
Package universe owns the fixed Starlark language surface.
Package universe owns the fixed Starlark language surface.
worker
Package worker implements the private same-executable parent/child transport.
Package worker implements the private same-executable parent/child transport.
Package mcpserver exposes CodeMode as exactly three official MCP tools.
Package mcpserver exposes CodeMode as exactly three official MCP tools.
mocks
Package mocks contains generated test doubles for MCP adapter ports.
Package mocks contains generated test doubles for MCP adapter ports.

Jump to

Keyboard shortcuts

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