mcp

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package mcp is Atlas's Model Context Protocol server: it lets an AI agent drive a running Atlas server through tools — deploy a BPMN model, manage design-time projects and artifacts, start an instance, complete human tasks, and inspect live runtime state.

Shape: an adapter over the HTTP API, on two transports

The server speaks JSON-RPC 2.0 and translates each tool call into an HTTP request against a running Atlas server; it holds no engine state of its own. Two transports share one dispatch path:

  • stdio (Serve) — newline-delimited JSON, one message per line. This is the MCP stdio transport a local client (Claude Desktop, Claude Code) spawns.
  • Streamable HTTP (ServeHTTP) — the remote transport. Mount it at a path such as /mcp and a remote client can reach the same tools. Mounted through api.WithMCP it sits inside the Atlas server's own access boundary, so under --auth a request without a credential is refused there; the transport then forwards whatever authenticated the caller to the API, so a tool call is exactly as privileged as whoever made it and no more (ADR-0196).

This is deliberate. The engine is a single-writer partition (invariant I3): exactly one goroutine may touch a partition's processor and state, a discipline the api package already enforces behind its HTTP surface. By proxying to that surface rather than embedding the engine, the MCP server can never violate an engine invariant — it only ever makes HTTP calls. It is a pure adapter, and an AI agent sees the same deployments and instances a human sees in the web UI.

Project deletion

A design-time project is a grouping folder, not an execution aggregate (ADR-0034). atlas_delete_project therefore calls the public project DELETE endpoint and removes only that folder. Drafts and decision references tagged with its id remain available as ungrouped artifacts; deployed definitions and process instances are unaffected. The API operation is idempotent and enforces the project owner role when authentication is enabled.

No new dependencies

The protocol is implemented by hand (see server.go), matching the repository's preference for small, self-contained code over pulled-in SDKs. The only surface area is the four MCP methods a tools-only server needs: initialize, tools/list, tools/call, and ping.

Running it

Remote (Streamable HTTP) — atlas serve mounts the transport at /mcp:

atlas serve --addr :8080            # engine + HTTP API + UI + /mcp

Local (stdio) — a per-agent, short-lived adapter an MCP client spawns:

atlas mcp --server http://localhost:8080
atlas mcp --server https://atlas.example.com --token "$ATLAS_TOKEN"

The token is what a stdio adapter authenticates with against a server running --auth, and is needed there: unlike the HTTP transport, which forwards each request's own caller, a stdio adapter is one process with one identity for its whole life. Without it every tool call comes back 401.

For stdio, diagnostics go to stderr; stdout carries protocol traffic only.

Index

Constants

View Source
const TransportHeader = "X-Atlas-Via-MCP"

TransportHeader marks an API request as one a tool call made, rather than one a client made directly against /api/v1 with the same credential.

Atlas stamps it on every request entering /mcp and this adapter forwards it, the same way it forwards the caller's own credential and for the same reason: what arrives at the API has to be recognisable as what it is. A token a person approved for the transport alone is otherwise confined away from the very API calls its tools are made of.

It is not a credential this adapter holds — it holds none (ADR-0196). It arrives on the request, is carried verbatim like the other two, and means nothing except to the server that wrote it.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client is a thin HTTP client for the Atlas server API (see the api package). The MCP server owns no engine state of its own; every tool call is translated into an HTTP request against a running Atlas server, which remains the single writer of its partition (invariant I3). That keeps the MCP surface a pure adapter — it can never violate an engine invariant because it never touches the engine directly.

func NewClient

func NewClient(baseURL string, opts ...ClientOption) *Client

NewClient builds a Client for the Atlas server at baseURL (e.g. "http://localhost:8080"). A trailing slash is tolerated.

type ClientOption

type ClientOption func(*Client)

ClientOption configures a Client at construction.

func WithBearer

func WithBearer(token string) ClientOption

WithBearer attaches an Authorization: Bearer <token> header to every request that carries no caller credential of its own. That is the stdio adapter's case: it is a per-agent process with one identity for its whole life, given on the command line (atlas mcp --token).

The HTTP transport does not use it. There, each request brings its own caller and forCaller takes precedence — see ADR-0196 for why the adapter no longer holds a credential of its own on that path.

An empty token is a no-op, so callers can pass it unconditionally.

func WithTLSRoots added in v0.5.0

func WithTLSRoots(pool *x509.CertPool) ClientOption

WithTLSRoots verifies the server's certificate against pool in addition to the host's roots, for the stdio adapter pointed at an https:// Atlas whose certificate an internal CA issued (atlas mcp --tls-ca).

It is a trust anchor and not a way around verification: there is no skip-verify switch here, in api/targetstore.go, or anywhere else in Atlas (ADR-0191). A nil pool leaves the client exactly as it was — verifying against the host's roots — so callers can pass it unconditionally.

type Server

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

Server is a Model Context Protocol server that exposes the Atlas API as MCP tools over a stdio JSON-RPC 2.0 transport. It is deliberately dependency-free and hand-written, in keeping with the rest of the repository.

func NewServer

func NewServer(client *Client) *Server

NewServer builds an MCP server that proxies tool calls to the Atlas server reachable through client.

func (*Server) Serve

func (s *Server) Serve(in io.Reader, out io.Writer) error

Serve runs the JSON-RPC loop, reading newline-delimited messages from in and writing responses to out, until in reaches EOF. It returns the first read error, or nil on a clean EOF. Diagnostics must never be written to out (that is the protocol channel); callers should log to stderr.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP makes Server an http.Handler implementing the MCP "Streamable HTTP" transport, so the same tool surface reachable over stdio (Serve) can be mounted at a path such as /mcp and reached by a remote MCP client — for example a claude.ai custom connector.

Message dispatch is shared with the stdio loop via handleWith; this method is transport only. The handler is stateless: it assigns no Mcp-Session-Id and requires none, which is sufficient for a tools-only server.

Authentication is the api package's, not this handler's: mount it with api.WithMCP and it sits inside the same boundary as every other route, so a request without a credential never reaches here. What this method does is the other half — it forwards the credential the request arrived with to the Atlas API, so a tool call is exactly as privileged as whoever made it. It carries no identity of its own to lend (ADR-0196).

type Tool

type Tool struct {
	Name        string
	Description string
	InputSchema map[string]any
	Handler     func(c *Client, args map[string]any) (string, error)
}

Tool is one MCP tool: its advertised name, human/model-facing description, JSON Schema for arguments, and the handler that fulfils a call by talking to the Atlas server.

Jump to

Keyboard shortcuts

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