Skip to content

HTTP API: mcp

The MCP projection of this registry, described as one typed value: who answers `initialize` and with which protocol versions, the transports and how many sessions each holds, what of the protocol is served and what is not, every tool with the effect and the hints its annotations are derived from, the tools that write the repository, the resources, and where each declared client's configuration stands in this repository. Nothing in it is a list of its own: the tools are the registry's, the effect is the capability's classification, the clients are the distribution's providers.

Rendered from docs/generated/openapi.json, which the executable generates from its capability registry and CI refuses stale. The raw document is at /openapi.json; a running server serves the same document at its own /openapi.json and Swagger UI at /swagger.

mcp

The MCP projection of this registry, described as one typed value: who answers `initialize` and with which protocol versions, the transports and how many sessions each holds, what of the protocol is served and what is not, every tool with the effect and the hints its annotations are derived from, the tools that write the repository, the resources, and where each declared client's configuration stands in this repository. Nothing in it is a list of its own: the tools are the registry's, the effect is the capability's classification, the clients are the distribution's providers.

GET /api/v1/mcp mcp.projection

The MCP projection of this registry

Who answers `initialize` and with which protocol versions; the transports and the sessions attached over each; the methods served, and that prompts and notifications are not; every tool (or only those with one effect) with its capability, effect and the hints its annotations are derived from; the tools that write the repository; the resources; and whether each client the distribution declares has a configuration here that starts this repository's server. Reads the registry and one file per declared client; writes nothing.

  • query
  • experimental
  • benchmark required
  • cache disabled
  • MCP tool majordomus_mcp
  • MCP resource {"name": "mcp", "uri": "majordomus://mcp"}

Query parameters

nametyperequireddescriptionexamples
effect ExecutionEffect | null no List only the tools with this effect: `read`, `process_state` or `repository_mutation`. Absent lists every tool. writers: "repository_mutation"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/mcp?effect=repository_mutation"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 McpProjection The MCP projection of this registry: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.

Schemas

The components only this tag's operations use. Each row is the type's own field, its doc comment the description; a type another page owns links there.

ExecutionHints

object
What a caller may assume about a call before making it: the four facts MCP names tool annotations, held once on the model so that no projection states its own.

Classified by ExecutionPolicy::hints, never declared.

use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy, Hints};
let read: Hints = ExecutionPolicy::classify(CapabilityKind::Query).hints();
assert_eq!(
    serde_json::to_value(read).unwrap(),
    serde_json::json!({ "read_only": true, "destructive": false, "idempotent": true, "open_world": false })
);
propertytyperequireddescription
read_only boolean yes The call changes nothing, anywhere.
destructive boolean yes The call may overwrite or remove something that outlives this process.
idempotent boolean yes A second identical call changes nothing the first did not.
open_world boolean yes The call reaches beyond this machine. No handler of this executable does: observing the forge and talking to an advisor are commands a person runs, not capabilities.

Used by McpToolEntry

McpClient

object
One client the distribution declares a project-scoped configuration for.

use majordomus_cli::capability::builtin::mcp::{McpClient, McpClientStanding};
let mut clients: Vec<McpClient> = serde_json::from_value(serde_json::json!([
    { "id": "gemini", "title": "Gemini CLI", "config": ".gemini/settings.json", "standing": "absent" },
    { "id": "claude-code", "title": "Claude Code", "config": ".mcp.json", "standing": "wired" },
])).unwrap();
// ordered by the provider's id, whatever order the distribution declared them in
majordomus_cli::order::canonical(&mut clients);
assert_eq!(clients[0].id, "claude-code");
assert_eq!(clients[0].standing, McpClientStanding::Wired);
propertytyperequireddescription
id string yes The provider id.
title string yes The name a person knows it by.
config string yes The file it reads, repository-relative.
standing McpClientStanding → McpClientStanding yes Where that file stands here.

Used by McpProjection

McpClientStanding

"wired" | "foreign" | "absent"
Where a client's project-scoped configuration stands in this repository.

use majordomus_cli::capability::builtin::mcp::McpClientStanding;
// the words a caller reads, as they are written on every surface
assert_eq!(serde_json::to_value(McpClientStanding::Wired).unwrap(), "wired");
assert_eq!(serde_json::to_value(McpClientStanding::Foreign).unwrap(), "foreign");
assert_eq!(serde_json::to_value(McpClientStanding::Absent).unwrap(), "absent");
  • wiredThe file exists and names the launcher: this client starts this repository's server.
  • foreignThe file exists and does not name the launcher: the client reads it and starts something else, or nothing.
  • absentThe file does not exist: this client starts no server here until it is written.

Used by McpClient

McpEffectCount

object
How many tools have one effect.

use majordomus_cli::capability::builtin::mcp::McpEffectCount;
use majordomus_cli::capability::Effect;
let c: McpEffectCount =
    serde_json::from_value(serde_json::json!({ "effect": "read", "tools": 149 })).unwrap();
assert_eq!((c.effect, c.tools), (Effect::Read, 149));
propertytyperequireddescription
effect ExecutionEffect → ExecutionEffect yes The effect.
tools integer (uint) yes How many tools have it.

Used by McpProjection

McpFinding

object
Something about the projection a person should act on.

use majordomus_cli::capability::builtin::mcp::McpFinding;
let f: McpFinding = serde_json::from_value(serde_json::json!({
    "code": "mcp_client_config_foreign",
    "message": ".mcp.json exists and does not name majordomus-mcp",
    "remedy": "add a `majordomus` server to .mcp.json whose command is majordomus-mcp",
})).unwrap();
// a finding always says what to do, not only what is wrong
assert!(!f.code.is_empty() && !f.remedy.is_empty());
propertytyperequireddescription
code string yes The stable code.
message string yes What is wrong.
remedy string yes What to do about it.

Used by McpProjection

McpProjection

object
The MCP projection of this registry in this repository.

use majordomus_cli::capability::builtin::mcp::McpProjection;
let p: McpProjection = serde_json::from_value(serde_json::json!({
    "server": { "name": "majordomus", "title": "Majordomus", "version": "0.14.0" },
    "protocol_versions": ["2025-06-18"],
    "transports": [{ "id": "stdio", "reached_by": "majordomus mcp", "attached": 0 }],
    "serving": { "methods": ["initialize"], "tools": true, "resources": true, "prompts": false, "notifications": false },
    "tool_count": 2,
    "tools": [],
    "effects": [{ "effect": "read", "tools": 1 }, { "effect": "repository_mutation", "tools": 1 }],
    "writers": ["majordomus_plan_transition"],
    "resources": { "builtin": 1, "objects": 0, "template": "majordomus://<kind>/<identity>" },
    "launcher_in_repository": false,
    "clients": [],
    "findings": [],
})).unwrap();
// the count is of every tool, whatever the `effect` filter narrowed `tools` to
assert_eq!(p.tool_count, p.effects.iter().map(|e| e.tools).sum::<usize>());
assert!(p.tools.is_empty() && p.writers.len() == 1);
propertytyperequireddescription
server McpServerIdentity → McpServerIdentity yes Who answers initialize.
protocol_versions array of string yes The protocol versions accepted, newest first.
transports array of McpTransportEntry → McpTransportEntry yes How a client reaches the server.
serving McpServing → McpServing yes What of the protocol is served.
tool_count integer (uint) yes How many tools the registry projects, whatever the filter asked for.
tools array of McpToolEntry → McpToolEntry yes The tools asked for, in registry order.
effects array of McpEffectCount → McpEffectCount yes The tools counted by effect, every effect present.
writers array of string yes The tools that write the repository, by name. The initialize instructions name the same ones.
resources McpResourceSummary → McpResourceSummary yes The resources.
launcher_in_repository boolean yes Whether this repository carries the launcher at bin/majordomus-mcp. Where it does not, the installed command of the same name is what a configuration names.
clients array of McpClient → McpClient yes The clients the distribution declares a configuration for, and where each stands.
findings array of McpFinding → McpFinding yes What a person should act on. Empty is nothing to do.

Used by mcp.projection

McpResourceSummary

object
The resources a client can read.

use majordomus_cli::capability::builtin::mcp::McpResourceSummary;
let r: McpResourceSummary = serde_json::from_value(serde_json::json!({
    "builtin": 54, "objects": 1742, "template": "majordomus://<kind>/<identity>",
})).unwrap();
// the two counts together are the length of `resources/list`
assert_eq!(r.builtin + r.objects, 1796);
propertytyperequireddescription
builtin integer (uint) yes Resources a builtin capability answers.
objects integer (uint) yes Objects of this repository's layer, each one more resource.
template string yes The URI shape of an object's resource.

Used by McpProjection

McpServerIdentity

object
Who answers initialize, as it answers.

use majordomus_cli::capability::builtin::mcp::McpServerIdentity;
let s: McpServerIdentity = serde_json::from_value(serde_json::json!({
    "name": "majordomus", "title": "Majordomus", "version": "0.14.0",
})).unwrap();
// the version is the executable's: the protocol adapter has none of its own to drift
assert_eq!((s.name.as_str(), s.version.as_str()), ("majordomus", "0.14.0"));
propertytyperequireddescription
name string yes The server name.
title string yes The name a person reads.
version string yes The version: this executable's, never one of the protocol adapter's own.

Used by McpProjection

McpServing

object
What the server serves of the protocol, and what it does not.

use majordomus_cli::capability::builtin::mcp::McpServing;
let s: McpServing = serde_json::from_value(serde_json::json!({
    "methods": ["initialize", "tools/call"], "tools": true, "resources": true,
    "prompts": false, "notifications": false,
})).unwrap();
// what is not served is stated, so a client does not learn it from a refusal
assert!(s.tools && !s.prompts && !s.notifications);
assert!(!s.methods.iter().any(|m| m.starts_with("prompts/")));
propertytyperequireddescription
methods array of string yes The methods a request may name. Anything else is answered -32601.
tools boolean yes Tools: every capability that declares one.
resources boolean yes Resources: every capability that declares one, and every object of the layer.
prompts boolean yes Prompts. Not served: the repository's prompt assets are resources, because a prompt served unrendered would read as finished.
notifications boolean yes Subscriptions and list-change notifications. Not served: this server sends nothing unasked.

Used by McpProjection

McpToolEntry

object
One tool, as the registry projects it.

use majordomus_cli::capability::builtin::mcp::McpToolEntry;
use majordomus_cli::capability::Effect;
let t: McpToolEntry = serde_json::from_value(serde_json::json!({
    "name": "majordomus_plan_transition", "capability": "plan.transition",
    "module": "plan", "title": "Move an issue", "effect": "repository_mutation",
    "hints": { "read_only": false, "destructive": true, "idempotent": false, "open_world": false },
})).unwrap();
assert_eq!(t.effect, Effect::RepositoryMutation);
// the hints are the effect's classification, carried beside it rather than restated
assert!(t.hints.destructive && !t.hints.read_only && !t.hints.idempotent);
propertytyperequireddescription
name string yes The name a client calls.
capability string yes The capability it projects; capabilities.describe answers its schemas.
module string yes The module that composes the capability.
title string yes The title.
effect ExecutionEffect → ExecutionEffect yes What a call changes.
hints ExecutionHints → ExecutionHints yes What a caller may assume before calling; the tool's annotations are this value.

Used by McpProjection

McpTransportEntry

object
One way a client reaches the server.

use majordomus_cli::capability::builtin::mcp::McpTransportEntry;
let t: McpTransportEntry = serde_json::from_value(serde_json::json!({
    "id": "stdio", "reached_by": "majordomus mcp", "attached": 1,
})).unwrap();
// a count of sessions at the moment of asking, not a claim that a server is running
assert_eq!((t.id.as_str(), t.attached), ("stdio", 1));
propertytyperequireddescription
id string yes stdio or http.
reached_by string yes How it is reached: the command a client starts, or the path on the shared server.
attached integer (uint) yes Sessions attached to this process over it right now.

Used by McpProjection

Searches the titles and descriptions of every page this site publishes.