Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion cartridges/local-coord-mcp/abi/LocalCoord/SafeLocalCoord.idr
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,25 @@ data TokenMatch : SessionToken -> SessionToken -> Type where
-- ═══════════════════════════════════════════════════════════════════════════

||| Known client type prefixes for the hybrid identity model.
||| e.g. "claude", "gemini", "copilot", "custom"
||| e.g. "claude", "gemini", "copilot", "custom", "openai", "mistral"
||| (Task #33: extended 2026-04 to cover OpenAI and Mistral families.)
public export
data ClientKind : Type where
Claude : ClientKind
Gemini : ClientKind
Copilot : ClientKind
Custom : ClientKind
Openai : ClientKind
Mistral : ClientKind

public export
Show ClientKind where
show Claude = "claude"
show Gemini = "gemini"
show Copilot = "copilot"
show Custom = "custom"
show Openai = "openai"
show Mistral = "mistral"

||| A peer identity: human-readable prefix + 4-character hex suffix.
||| e.g. "claude-7f3a", "gemini-b2c1"
Expand Down Expand Up @@ -231,12 +236,16 @@ clientKindToInt Claude = 0
clientKindToInt Gemini = 1
clientKindToInt Copilot = 2
clientKindToInt Custom = 3
clientKindToInt Openai = 4
clientKindToInt Mistral = 5

public export
intToClientKind : Int -> ClientKind
intToClientKind 0 = Claude
intToClientKind 1 = Gemini
intToClientKind 2 = Copilot
intToClientKind 4 = Openai
intToClientKind 5 = Mistral
intToClientKind _ = Custom

||| FFI: Get the bind port.
Expand Down
353 changes: 335 additions & 18 deletions cartridges/local-coord-mcp/adapter/local_coord_adapter.zig

Large diffs are not rendered by default.

171 changes: 167 additions & 4 deletions cartridges/local-coord-mcp/cartridge.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,44 @@
"tier": "Ayo",
"tools": [
{
"description": "Register this instance as a coordination peer. Returns a peer ID and a session token for all subsequent calls. Optional `context` (alphanumeric + hyphen/underscore, max 32 bytes) disambiguates multiple windows of the same client_kind. Optional `declared_affinities` is an array of tag names the peer self-reports as strengths — feeds the reassignment engine (Task #14).",
"description": "Register this instance as a coordination peer. Returns a peer ID and a session token for all subsequent calls. Optional `context` (alphanumeric + hyphen/underscore, max 32 bytes) disambiguates multiple windows of the same client_kind. Optional `declared_affinities` is an array of tag names the peer self-reports as strengths — feeds the reassignment engine (Task #14). Optional `variant` is a free-form model identifier (Task #33). Optional `capabilities` advertises class / tier / prover_strengths for cold-start routing (Task #34).",
"inputSchema": {
"properties": {
"capabilities": {
"description": "Capability advertisement used for cold-start routing (Task #34). All three keys are individually optional.",
"properties": {
"class": {
"description": "Capability classes (e.g. 'reasoning', 'coding', 'proof', 'grammar'). CSV internally, max 128 bytes total.",
"items": {
"type": "string"
},
"type": "array"
},
"prover_strengths": {
"description": "Prover names this peer claims strength in (e.g. 'coq', 'lean', 'tlaps'). CSV internally, max 256 bytes total.",
"items": {
"type": "string"
},
"type": "array"
},
"tier": {
"description": "Advertised capability tier 1..5 (0 = unset).",
"maximum": 5,
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"client_kind": {
"description": "Client type: claude, gemini, copilot, or custom",
"description": "Client family: claude, gemini, copilot, openai, mistral, or custom (Task #33 extended openai + mistral).",
"enum": [
"claude",
"gemini",
"copilot",
"custom"
"custom",
"openai",
"mistral"
],
"type": "string"
},
Expand All @@ -61,6 +89,10 @@
"supervised"
],
"type": "string"
},
"variant": {
"description": "Free-form model/variant label (Task #33). Alphanumeric + `.`/`-`/`_` only, max 32 bytes. e.g. 'opus-4.7', 'flash-2.5', 'leanstral'.",
"type": "string"
}
},
"required": [
Expand Down Expand Up @@ -463,7 +495,138 @@
"type": "object"
},
"name": "coord_transfer_master"
},
{
"description": "Set or update this peer's free-form model/variant label after registration (Task #33). Alphanumeric + `.`/`-`/`_` only, max 32 bytes. Empty clears.",
"inputSchema": {
"properties": {
"token": {
"description": "Session token from coord_register",
"type": "string"
},
"variant": {
"description": "Variant label (e.g. 'opus-4.7', 'flash-2.5', 'leanstral')",
"type": "string"
}
},
"required": [
"token",
"variant"
],
"type": "object"
},
"name": "coord_set_variant"
},
{
"description": "Set or update this peer's advertised capabilities (Task #34). Any omitted key is cleared.",
"inputSchema": {
"properties": {
"class": {
"description": "Capability classes (CSV internally, max 128 bytes).",
"items": {
"type": "string"
},
"type": "array"
},
"prover_strengths": {
"description": "Prover strengths (CSV internally, max 256 bytes).",
"items": {
"type": "string"
},
"type": "array"
},
"tier": {
"description": "Advertised capability tier 1..5 (0 = unset).",
"maximum": 5,
"minimum": 0,
"type": "integer"
},
"token": {
"description": "Session token from coord_register",
"type": "string"
}
},
"required": [
"token"
],
"type": "object"
},
"name": "coord_set_capabilities"
},
{
"description": "Read another peer's advertised capabilities (Task #34). Used by the routing layer for cold-start dispatch when track_record is thin.",
"inputSchema": {
"properties": {
"peer_id": {
"description": "Target peer_id (<kind>-<4hex>[@<context>])",
"type": "string"
},
"token": {
"description": "Own session token",
"type": "string"
}
},
"required": [
"token",
"peer_id"
],
"type": "object"
},
"name": "coord_get_peer_capabilities"
},
{
"description": "Read-only snapshot of coord-mcp state: active peer count (with per-kind / per-role breakdown), pending quarantine depth, active claims, track-record fill, and recent reject counts with cooldown flags. Lets other tooling monitor coord health without walking every export individually.",
"inputSchema": {
"properties": {
"token": {
"description": "Session token from coord_register — any active peer may poll.",
"type": "string"
}
},
"required": [
"token"
],
"type": "object"
},
"name": "coord_health"
},
{
"description": "Heartbeat for a held claim — resets the watchdog TTL (DD-20). Apprentice TTL is 30 s, journeyman 5 min, master no watchdog. Long-running work should ping this periodically so the server doesn't auto-release the claim.",
"inputSchema": {
"properties": {
"task": {
"description": "Task identifier previously claimed via coord_claim_task",
"type": "string"
},
"token": {
"description": "Session token from coord_register",
"type": "string"
}
},
"required": [
"token",
"task"
],
"type": "object"
},
"name": "coord_progress"
},
{
"description": "Explicit watchdog sweep — release any claim whose holder has missed its role-based TTL. The sweep also runs implicitly at the top of every coord_claim_task, so this tool is only needed by ops wanting an external tick.",
"inputSchema": {
"properties": {
"token": {
"description": "Session token from coord_register — any active peer may invoke.",
"type": "string"
}
},
"required": [
"token"
],
"type": "object"
},
"name": "coord_sweep_watchdog"
}
],
"version": "0.6.0"
"version": "0.9.0"
}
119 changes: 115 additions & 4 deletions cartridges/local-coord-mcp/cartridge.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
spdx = "PMPL-1.0-or-later",
copyright = "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
name = "local-coord-mcp",
version = "0.3.0",
version = "0.9.0",
description = "Localhost multi-instance coordination — peer discovery, message passing, and task claiming for parallel AI sessions on the same machine",
domain = "ai",
tier = "Ayo",
Expand All @@ -35,14 +35,14 @@
tools = [
{
name = "coord_register",
description = "Register this instance as a coordination peer. Returns a peer ID and a session token for all subsequent calls. Optional `context` (alphanumeric + hyphen/underscore, max 32 bytes) disambiguates multiple windows of the same client_kind — peer_id becomes <kind>-<4hex>@<context>.",
description = "Register this instance as a coordination peer. Returns a peer ID and a session token for all subsequent calls. Optional `context` (alphanumeric + hyphen/underscore, max 32 bytes) disambiguates multiple windows of the same client_kind — peer_id becomes <kind>-<4hex>@<context>. Optional `variant` is a free-form model identifier (e.g. `opus-4.7`, `flash-2.5`, `leanstral`). Optional `capabilities` advertises class / tier / prover_strengths for cold-start routing (Task #34).",
inputSchema = {
type = "object",
properties = {
client_kind = {
type = "string",
description = "Client type: claude, gemini, copilot, or custom",
enum = ["claude", "gemini", "copilot", "custom"],
description = "Client family: claude, gemini, copilot, openai, mistral, or custom (Task #33).",
enum = ["claude", "gemini", "copilot", "custom", "openai", "mistral"],
},
context = {
type = "string",
Expand All @@ -53,6 +53,32 @@
description = "Optional requested role (DD-32). master is ALWAYS rejected here — promote via coord_promote_to_master. Default derived from client_kind (claude->journeyman, others->apprentice). Old names (executor, supervised) accepted as aliases for one release.",
enum = ["journeyman", "apprentice", "executor", "supervised"],
},
variant = {
type = "string",
description = "Free-form model/variant label (Task #33). Alphanumeric + `.`/`-`/`_` only, max 32 bytes. e.g. `opus-4.7`, `flash-2.5`, `leanstral`.",
},
capabilities = {
type = "object",
description = "Capability advertisement used for cold-start routing (Task #34). All three keys are individually optional.",
properties = {
class = {
type = "array",
description = "Capability classes (e.g. `reasoning`, `coding`, `proof`, `grammar`). Joined as CSV internally, max 128 bytes total.",
items = { type = "string" },
},
tier = {
type = "integer",
description = "Advertised capability tier 1..5 (0 = unset).",
minimum = 0,
maximum = 5,
},
prover_strengths = {
type = "array",
description = "Prover names this peer claims strength in (e.g. `coq`, `lean`, `tlaps`). CSV internally, max 256 bytes total.",
items = { type = "string" },
},
},
},
},
required = ["client_kind"],
},
Expand Down Expand Up @@ -218,5 +244,90 @@
required = ["token", "request_id", "reason"],
},
},
{
name = "coord_set_variant",
description = "Set or update this peer's free-form model/variant label after registration (Task #33). Alphanumeric + `.`/`-`/`_` only, max 32 bytes. Empty clears.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Session token from coord_register" },
variant = { type = "string", description = "Variant label (e.g. `opus-4.7`, `flash-2.5`, `leanstral`)" },
},
required = ["token", "variant"],
},
},
{
name = "coord_set_capabilities",
description = "Set or update this peer's advertised capabilities (Task #34). Any omitted key is cleared.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Session token from coord_register" },
class = {
type = "array",
description = "Capability classes (CSV internally, max 128 bytes).",
items = { type = "string" },
},
tier = {
type = "integer",
description = "Advertised capability tier 1..5 (0 = unset).",
minimum = 0,
maximum = 5,
},
prover_strengths = {
type = "array",
description = "Prover strengths (CSV internally, max 256 bytes).",
items = { type = "string" },
},
},
required = ["token"],
},
},
{
name = "coord_get_peer_capabilities",
description = "Read another peer's advertised capabilities (Task #34). Used by the routing layer for cold-start dispatch when track_record is thin.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Own session token" },
peer_id = { type = "string", description = "Target peer_id (<kind>-<4hex>[@<context>])" },
},
required = ["token", "peer_id"],
},
},
{
name = "coord_progress",
description = "Heartbeat for a held claim — resets the watchdog TTL (DD-20). Apprentice TTL is 30 s, journeyman 5 min, master no watchdog. Long-running work should ping this periodically so the server doesn't auto-release the claim.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Session token from coord_register" },
task = { type = "string", description = "Task identifier previously claimed via coord_claim_task" },
},
required = ["token", "task"],
},
},
{
name = "coord_sweep_watchdog",
description = "Explicit watchdog sweep — release any claim whose holder has missed its role-based TTL. The sweep also runs implicitly at the top of every coord_claim_task, so this tool is only needed by ops wanting an external tick.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Session token from coord_register — any active peer may invoke." },
},
required = ["token"],
},
},
{
name = "coord_health",
description = "Read-only snapshot of coord-mcp state: active peer count (with per-kind / per-role breakdown), pending quarantine depth, active claims, track-record fill, and recent reject counts with cooldown flags. Lets other tooling monitor coord health without walking every export individually.",
inputSchema = {
type = "object",
properties = {
token = { type = "string", description = "Session token from coord_register — any active peer may poll." },
},
required = ["token"],
},
},
],
}
Loading