Skip to content

MCP

What MCP does here

MCP is the agent-facing protocol surface for clumsies. It is how an agent discovers available material, loads the specific rules, workflows, and context it needs, declares which constraints it actually applied, and proposes edits back into the system.

That makes MCP more than a transport layer. It is the runtime contract between agent work and the managed rule, context, and attestation model.

The current tool surface

The current implementation exposes these MCP tools:

Tool familyTools
session and attestationmemsetup, memdisc, memload, memref, agentreport, agentrejected
artifact mutationsartifact

This is the real protocol surface in the running code. The server test suite explicitly asserts that memory.begin, memory.complete, memory.startup, memory.list, and memory.activate are not part of the public tool list. The older context.propose_*, rule.propose_*, and draft tool surfaces are also not public MCP tools anymore; local content changes go through artifact.

The core runtime cycle

The stable mental model now matches the current META_PROMPT very closely:

  1. bootstrap the session with memsetup
  2. discover relevant material with memdisc
  3. load only the content the task actually needs with memload
  4. apply the loaded rules in the work
  5. declare applied constraints with memref
  6. use artifact when the task is to refine rules, context, or MPF
  7. close the turn with agentreport or agentrejected

That cycle is the runtime expression of the whole product:

  • Hub publishes authoritative state
  • local cache keeps runtime fast
  • MCP serves that state to the agent
  • attestation records what actually happened

Result envelope

Every successful tool call is wrapped in the same envelope shape:

json
{
  "content": [
    {
      "type": "text",
      "text": "{...serialized structured result...}"
    }
  ],
  "structuredContent": {
    "...": "tool-specific payload"
  },
  "isError": false
}

Error results use the same outer shape, but set isError to true and place an error string under structuredContent.error.

This detail matters because the protocol is not only human-readable. Agents are expected to consume the machine-readable structuredContent payload directly.

memsetup

memsetup bootstraps the session. It returns the current workspace identity, the current session ID, and the current META_PROMPT frame.

memsetup is a binding operation. The caller must pass the real host session or thread ID supplied by the adapter. Agents should call it once at session startup, before any other clumsies MCP tool. Repeated calls are only for an explicit user-invoked setup flow.

Input

FieldTypeRequiredMeaning
session_idstringyeshost-agent session or thread id
knownHashesobject mapyesmust include META_PROMPT.md; pass the remembered hash, or "" when unknown

Structured result

FieldMeaning
workspaceIdauthoritative workspace ID
sessionIdsession identifier used to group later attestation events
mpf.hashcurrent META_PROMPT hash
mpf.contentcurrent META_PROMPT content when changed or initially loaded
mpf.changedfalse when the caller already knows the same hash

A typical result looks like this:

json
{
  "workspaceId": "ws-4a5c282474c9b5d9385dec0502267738",
  "sessionId": "4f04001af902673e92094a7c59d86abb",
  "mpf": {
    "hash": "1eb791139b9f265846dc2d0d8d6a0c1ce5116a245c42829838ddcb492fc13337",
    "content": "# clumsies\n..."
  }
}

In the current runtime, that meta-prompt frame comes from the workspace-scoped META_PROMPT.md asset. The session object also records a local .setup attestation event when the session is created.

The current bootstrap content is intentionally simpler than earlier revisions. It now frames the protocol as discover -> load -> apply -> refer -> refine -> submit, and its priority model is loaded rules > this meta-prompt > your defaults.

memdisc

memdisc discovers available rules, workflows, and context files without loading their full content.

Input

FieldTypeRequiredMeaning
kindstring enumnoone of rule, workflow, context
groupstringnofilter by first path segment or logical group
querystringnofree-text query across searchable metadata

Structured result

The tool returns:

json
{
  "items": [
    {
      "id": "p-e60e775a-fc91-4780-bd32-2bb451404298",
      "kind": "workflow",
      "path": "workflow/CODING.md",
      "name": "CODING",
      "group": "workflow",
      "hash": "sha256:..."
    }
  ]
}

Each item can include:

FieldMeaning
idstable object ID
kindrule, workflow, or context
pathcurrent workspace-relative path
namedisplay name derived from the path
groupoptional group value
hashcurrent content hash
descriptionoptional metadata description when present
hasDraftwhether the object currently has a local draft

Discover is inventory, not content delivery. Its job is to let the agent choose what is relevant before spending context window on full content.

Create-only drafts have no Hub-issued object ID yet. The client assigns them a deterministic tmp-* ID when the draft is created, and memdisc exposes that temporary ID as the public id. Agents should use that ID for later memload calls or for artifact operations such as delete and discard. Draft paths are not a public identity for create-only drafts.

memload

memload resolves full content for the selected IDs. This is where protocol flow stops being inventory and becomes working task context.

Input

FieldTypeRequiredMeaning
idsstring arrayyesone or more rule, workflow, or context IDs
knownHashesobject mapyes{id: hash} map for delta loading; include every requested id

Each ids entry must also be present in knownHashes. Pass the remembered hash when available. Pass an empty string when the caller explicitly does not know the hash yet. Omitting knownHashes, or omitting one requested id from the map, is invalid.

Structured result

The tool returns:

json
{
  "workspaceId": "ws-4a5c282474c9b5d9385dec0502267738",
  "items": [
    {
      "id": "p-e60e775a-fc91-4780-bd32-2bb451404298",
      "kind": "workflow",
      "path": "workflow/CODING.md",
      "changed": true,
      "hash": "sha256:...",
      "hasDraft": false,
      "content": "# ...",
      "constraints": [
        {
          "id": "Steps",
          "name": "Steps",
          "text": "Inspect the diff and suggest a commit message.",
          "textHash": "..."
        }
      ]
    }
  ]
}

Important item fields are:

FieldMeaning
changedwhether the current hash differs from the caller's knownHashes entry
hashcurrent content hash
hasDraftwhether the loaded result resolves to draft-aware state
draftBaseHashoptional base hash when draft-aware content is involved
contentfull text content, or null when unchanged under delta loading
constraintsreferable rule/workflow constraint entries parsed from the loaded content

For rules and workflows, the returned content includes the refer reminder footer. Context items do not get that footer.

Delta loading only suppresses repeated content text. For rule and workflow items, constraints are still returned when changed is false and content is null, because agents need those stable entries to call memref without guessing from markdown.

In this protocol, a constraint is a referable semantic markdown section in a rule or workflow file. It is either a whole H2 section, or one list item inside an H2 section. A whole H2 section uses the H2 title as its stable returned id. A list item uses H2 title/ordinal, such as Steps/1 and Steps/2. The name field is the H2 title used for display/grouping, and text is the H2 body or list item content. Agents must copy the returned id exactly into the constraintId wire field in memref; they must not invent IDs.

memref

memref is the strongest usage signal in the model. It is the point where the agent claims that one of the constraints entries returned by memload for a rule or workflow actually shaped the turn.

Context files are reference material, not refer targets. A context ID supplied as ruleId is rejected.

Input

FieldTypeRequiredMeaning
refsobject arrayyesone or more declared constraint references

Each ref object can contain:

FieldTypeRequiredMeaning
ruleIdstringyesstable rule or workflow ID
constraintIdstringyeswire field containing an exact returned constraints[].id value
ruleHashstringnocurrent content hash when available
reasonstringnohuman-readable explanation of why the constraint mattered

Structured result

json
{
  "ok": true,
  "count": 2
}

count is the number of accepted reference objects processed in that call.

Retryable errors

memref validation errors are structured so agents can retry instead of treating the text message as opaque. Unknown rule/workflow IDs tell the agent to rediscover and reload. Unknown constraint IDs include the valid constraint candidates for that rule/workflow when available.

Example invalid constraint response:

json
{
  "error": "memref constraintId 'Step' is not valid for ruleId 'p-...'; retry with one of: Steps",
  "code": "unknown_constraint",
  "retryable": true,
  "retryAction": "retry_with_valid_constraint",
  "validConstraints": [
    {
      "id": "Steps",
      "name": "Steps",
      "text": "Inspect the diff and suggest a commit message."
    }
  ]
}

Agents should use validConstraints[].id exactly.

agentreport

agentreport closes a successful turn by recording the agent summary.

Input

FieldTypeRequiredMeaning
summarystringyesshort summary of the completed work

Validation

  • summary must be present
  • summary must be a string
  • summary must not be empty

Structured result

json
{
  "ok": true
}

In the current implementation, this records an .agent_report attestation event.

agentrejected

agentrejected closes an unsatisfactory turn when the output did not follow loaded constraints.

Input

FieldTypeRequiredMeaning
reasonstringnooptional rejection reason

Structured result

json
{
  "ok": true
}

In the current implementation, this records a .reject attestation event.

artifact

artifact stages local changes for Artifact rules, workspace context, or MPF. Those local changes are stored as drafts until they enter review.

The input is a tagged command object:

json
{
  "resource": "context",
  "op": {
    "update": {
      "id": "ctx-123",
      "body": "# New content\n",
      "description": "Clarify setup notes"
    }
  }
}

op must contain exactly one key. The protocol has one public MCP tool, and payloads stay typed.

Top-level input

FieldTypeRequiredMeaning
resourcestring enumyesone of context, rule, or mpf
optagged objectyestagged operation

create

Creates a new local artifact change.

FieldTypeRequiredMeaning
pathstringyestarget path for the new draft
bodystringyesdraft content
descriptionstringnooptional human-facing summary

Structured result

json
{
  "ok": true,
  "draft_path": "spec/new-context.md"
}

update

Creates or updates an update change against an existing object. For context and rule, the implementation resolves id through the manifest, reads the current cached file, computes a base hash, and writes the local draft form. For MPF, id should be META_PROMPT.md.

If a matching update draft already exists, update replaces its content and keeps it in draft state. This is what allows agents to refine a local context or rule draft through MCP instead of writing draft files directly.

FieldTypeRequiredMeaning
idstringyescontext id, rule id, or META_PROMPT.md
bodystringyesreplacement draft body
descriptionstringnooptional summary

rename

Creates a rename change. rename is valid for context and rule; MPF has the reserved path META_PROMPT.md and cannot be renamed.

FieldTypeRequiredMeaning
idstringyescontext id or rule id
new_pathstringyesproposed new path
descriptionstringnooptional summary

delete

Creates a delete draft for an existing resource. If delete targets a create-only draft with no manifest entry, the client treats the call as discarding that create draft. In that create-only case, id must be the tmp-* local ID returned by memdisc; draft paths are not accepted as public identity.

FieldTypeRequiredMeaning
idstringyesresource id, create-draft temp id, or MPF
descriptionstringnooptional summary

discard

Discards an existing draft object. This is different from delete: delete proposes deletion of a real resource. discard removes an unsubmitted draft.

FieldTypeRequiredMeaning
idstringyesany draft or resource identifier

Current error behavior

Several validation and runtime errors are already stable enough to document:

SituationResult
invalid argument types or missing required fieldsisError: true with an error message
unknown tool nameUnknown tool
memsetup omits knownHashes.META_PROMPT.mdisError: true with an invalid params error
memload omits knownHashes or an entry for a requested IDisError: true with an invalid params error
memload receives an unknown rule IDUnknown rule id
memref receives an unknown rule/workflow IDstructured code: "unknown_rule_or_workflow", retryable: true, retryAction: "rediscover_and_reload"
memref receives an invalid constraint IDstructured code: "unknown_constraint", retryable: true, retryAction: "retry_with_valid_constraint", optional validConstraints
artifact path is unsafeunsafe path
artifact target is missingfile not found in cache
artifact update conflicts with a non-update local draftartifact already has an incompatible local change
artifact delete targets a create-only draft by pathfile not found in cache
create collides with an existing draftdraft already exists

For agentreport, validation is slightly stricter than the schema summary alone suggests. summary is required, must be a string, and must not be empty.

MCP and attestation

The protocol is tightly coupled to attestation, but not in a noisy way.

Each meaningful runtime action records structured local evidence. memdisc, memload, memref, agentreport, agentrejected, and artifact operations generate attestation events that later feed Hub-side aggregation.

This is one reason clumsies is different from plain prompt storage. The protocol is not there only to serve content. It is there to make rule use and content-change proposals legible.