laya-mcp
Provides local decision-making capabilities powered by Apple's Core ML and ANE, enabling bounded text classification, scoring, and filtering for applications on Apple Silicon.
Integrates with Hugging Face to load a Core ML model checkpoint, supporting local model inference for decision-making tasks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@laya-mcpbatch decide which of these three commits are risky"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
laya-mcp
laya-mcp is a persistent local Model Context Protocol
server for bounded decisions powered by
Laya-CoreML. It loads one Core ML model at
process startup and keeps it resident for every MCP request.
Codex CLI ──────┐
Claude Code ────┼── MCP stdio ──> laya-mcp ──> Laya-CoreML ──> Core ML / ANE
Other clients ──┘The core server contains no client-specific behavior. Client examples live under
examples/, and client notes live under docs/.
Status
The current server provides:
one model load per server process through the MCP server lifespan;
a stable generic
info,decide,batch_decide, and conservativefiltertool surface;public
binary,choice, andordered_scoredecision semantics;structured confidence, probabilities, token usage, and inference latency;
explicit rejection before inference if an input would be truncated;
serialized access to the resident Core ML model;
JSON logs on stderr, leaving stdout exclusively for MCP stdio messages.
Milestones 2–4 add exact Laya 0.1 token accounting, deterministic reusable chunk
planning, composition/throughput benchmarks, stable decision primitives, and the
conservative context-reduction filter primitive. See
docs/laya-capabilities.md and
docs/token-efficiency.md, plus
docs/filtering.md.
This is alpha software. Laya decisions are probabilistic signals, not authorization, safety, legal, medical, or financial judgments.
Related MCP server: apple-fm-mcp
Requirements
Apple Silicon Mac
macOS 15 or newer for the default ANE checkpoint
Python 3.12 or 3.13 (3.12 is the currently validated project environment)
The default aac6fef/laya-multilingual-coreml-ane checkpoint supports a maximum of
96 total tokens across the question, options, and context. Call info rather than
hard-coding that limit if you configure another model.
Install
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'On first startup, Laya-CoreML may download the configured Hugging Face model before
loading it. Inference is local after the model is present. To require a cached model
or local model directory, set LAYA_MCP_LOCAL_FILES_ONLY=true or set
LAYA_MCP_MODEL to that directory.
Run the stdio server:
laya-mcpDo not print application output to stdout when using stdio transport. Server logs are structured JSON on stderr.
Tools
info
Reports the laya-mcp and backend versions, configured model, initialization state,
platform, Python version, Core ML compute units, known model limits, and process-local
metrics. The initialization duration is for this process on this machine.
decide
Arguments:
context: the small bounded text to evaluate;question: the decision instruction;decision: optional object withkind(binary,choice, orordered_score) and, for non-binary decisions, at least twooptions;confidence_threshold: optional number from 0 through 1;request_id: optional caller-defined correlation ID.
Example arguments:
{
"context": "player_controller.gd contains movement, jumping, acceleration and player animation logic.",
"question": "Is this file relevant to fixing a player movement bug?",
"request_id": "decision-17",
"confidence_threshold": 0.8
}The result includes the normalized result, model confidence, threshold outcome, applicable probability distribution, model/backend identifiers, local token usage, and measured inference latency.
batch_decide
batch_decide accepts ordered items with unique IDs. Use either:
shared_contextwith item contexts omitted; oran independent
contexton every item withshared_contextomitted.
The default fail_fast policy validates every item before inference and fails the
whole call if any item is invalid. partial returns an explicit error entry in the
original position for every failed item. No item is silently omitted.
Compact responses are the default and omit probability maps and per-item latency.
Set response_detail to detailed when those fields are needed. Backend/model
identifiers and aggregate metrics appear once at the response envelope.
{
"shared_context": "Choose components relevant to a movement regression.",
"confidence_threshold": 0.75,
"items": [
{"id": "a", "question": "Is the player controller relevant?"},
{"id": "b", "question": "Is the audio mixer relevant?"}
]
}This is MCP/API batching, not concurrent or fused model inference. The default ANE
backend evaluates each question independently while holding the same serialization
lock used by decide.
The server does not read files: clients must provide bounded context.
filter
filter accepts a criterion and ordered {id, text} candidates. It returns only
retained candidates by default, which keeps rejected classification records out of
the primary agent's context. Candidates are excluded only when Laya returns a
binary negative result with confidence at or above the rejection_threshold (the
default is 0.9). Relevant, uncertain, oversized, and failed candidates are
retained. Use response_detail: "detailed" for per-candidate diagnostics.
{
"criterion": "Relevant to fixing player acceleration behavior",
"rejection_threshold": 0.9,
"candidates": [
{"id": "movement", "text": "player controller handles acceleration"},
{"id": "audio", "text": "audio mixer loads music"}
]
}Filtering reports candidate reduction and serialized MCP payload sizes. Those are
local MCP payload measurements, not Codex/Claude token savings. See
docs/filtering.md for the conservative policy and benchmarks.
Configuration
Variable | Default | Meaning |
|
| Hugging Face ID or local directory |
| unset | Optional model revision |
|
| Disable model downloads/lookups |
| model default |
|
|
| Structured stderr log level |
The model is loaded before the MCP server accepts requests. Give clients a startup timeout comfortably above the model's measured initialization time on your machine. The original development machine measured about 30.35 seconds; that is a local observation, not a general performance claim.
Client setup
Generic MCP:
docs/mcp.mdCodex CLI:
docs/codex.mdClaude Code:
docs/claude-code.mdAgent usage patterns:
docs/coding-agents.mdEvaluation results:
docs/evaluation.mdModel comparison:
docs/model-comparison.mdCodex end-to-end evaluation:
docs/codex-evaluation.md
Development
python -m pytestThe real-model benchmark is opt-in and runs only on a compatible Apple Silicon machine:
python benchmarks/token_composition.py
python benchmarks/token_efficiency.py --output /tmp/laya-token-efficiency.json
python benchmarks/evaluate_milestone5.py --output evaluation/results/milestone5.jsonUnit and MCP integration tests use fake backends and do not load model weights. A
real smoke test should be run on a compatible Apple Silicon Mac before release.
The Milestones 5–6 quality evaluations are intentionally advisory; see
docs/evaluation.md before using filter for automatic
context exclusion.
Design constraints
no cloud LLM fallback;
no autonomous action loop;
no filesystem mutation or command execution;
no implicit input truncation;
every decision remains bounded and independently token-validated;
backend and MCP transport remain separate so other local Laya backends can be added.
License
Apache-2.0. Laya-CoreML and model weights are separate dependencies with their own licenses, notices, and model cards.
Available Tools
4 toolsbatch_decideARead-onlyIdempotent
Make ordered bounded decisions in one MCP request.
Supply shared_context and omit item contexts, or omit shared_context and
give every item its own context. This is API batching, not parallel inference.
| Name | Required | Description | Default |
|---|---|---|---|
| items | Yes | ||
| failure_policy | No | fail_fast | |
| shared_context | No | ||
| response_detail | No | compact | |
| confidence_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| model | Yes | |
| backend | Yes | |
| metrics | Yes | |
| failure_policy | Yes | |
| response_detail | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, and non-destructive behavior, so the bar is lower. The description adds meaningful behavioral context by stating decisions are 'ordered' and that this is 'API batching, not parallel inference,' which is not captured by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loads the main purpose, and contains no filler. The either/or context rule is concise and directly actionable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core batching semantics and the key context-mode constraint, and an output schema exists to describe return values. However, for a 5-parameter tool with several enums, it leaves failure_policy and response_detail semantics implicit and does not differentiate from the `decide` sibling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must compensate for parameter meaning. It usefully clarifies the shared_context vs. item-context relationship, but it does not explain failure_policy, response_detail, or confidence_threshold beyond their names and enum values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Make ordered bounded decisions in one MCP request.' It clearly conveys batch scope and distinguishes itself from parallel inference, though it does not explicitly contrast with the sibling `decide` tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit either/or usage rule: supply `shared_context` and omit item contexts, or omit `shared_context` and provide per-item contexts. It does not state when to prefer this over `decide` or `filter`, but the batching context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
decideARead-onlyIdempotent
Make one bounded decision using the resident local model.
Decision kinds are binary, choice, and ordered_score. The server only
signals needs_escalation; the caller remains responsible for any escalation.
| Name | Required | Description | Default |
|---|---|---|---|
| context | Yes | ||
| decision | No | ||
| question | Yes | ||
| request_id | No | ||
| confidence_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| model | Yes | |
| result | Yes | |
| backend | Yes | |
| details | No | |
| confidence | No | |
| request_id | No | |
| input_tokens | Yes | |
| decision_type | Yes | |
| output_tokens | Yes | |
| needs_escalation | Yes | |
| confidence_threshold | No | |
| inference_latency_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: the result is bounded, uses a local model, and the server only signals needs_escalation while the caller retains escalation responsibility.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three tight sentences with no filler. The core purpose is front-loaded, and the decision-kind and escalation notes each earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With five parameters and zero schema-level property descriptions, the tool description should explain how the parameters interrelate, but it only covers decision kinds and escalation signaling. It does not mention how to provide context/question or what confidence_threshold controls, leaving a significant gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description does not explain required parameters like context and question or optional ones like confidence_threshold and request_id. It only elaborates on decision kinds, which is one small part of the decision parameter, leaving most parameter semantics to inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Make one bounded decision'), identifies the resource ('resident local model'), and distinguishes itself from the sibling batch_decide by emphasizing 'one'. Listing the decision kinds further clarifies the exact scope of the tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'one bounded decision' phrasing implies single-use versus batch_decide, and 'resident local model' gives context, but there is no explicit when-to-use or when-not-to-use instruction. The escalation note describes caller responsibility but not how to choose among the sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
filterBRead-onlyIdempotent
Conservatively retain relevant, uncertain, failed, and oversized candidates.
Only a sufficiently confident irrelevant result excludes a candidate. The
default response returns selected candidate text and aggregate metrics; use
detailed for per-candidate diagnostics.
| Name | Required | Description | Default |
|---|---|---|---|
| criterion | Yes | ||
| candidates | Yes | ||
| response_detail | No | compact | |
| rejection_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| details | No | |
| metrics | Yes | |
| summary | Yes | |
| failures | Yes | |
| selected | Yes | |
| response_detail | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already supply read-only, idempotent, and non-destructive signals, so the description adds genuinely new behavioral context: the conservative exclusion policy and the option between compact and detailed responses. This is useful beyond what the annotations can express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense, front-loaded sentences with no filler. The first sentence states the core policy, the second clarifies both the exclusion rule and the response-mode option, and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Annotations and an output schema offset the need to explain side effects and return values, and the description covers the core policy and response modes. The main gaps are the undefined `criterion` parameter and the lack of routing guidance against sibling tools, which makes the definition adequate but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description compensates only partially. It hints at `response_detail` with 'use `detailed`' and at `rejection_threshold` with 'sufficiently confident,' but it never explains `criterion`, the candidate contract, or how the numerical threshold maps to rejection. Parameter names and defaults must carry most of the semantic burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a concrete action and scope: conservatively retain relevant, uncertain, failed, and oversized candidates. The threshold sentence further sharpens the behavior—only a sufficiently confident irrelevant result excludes a candidate—which clearly distinguishes it from a plain 'decide' tool. However, it never explicitly names or contrasts the sibling tools, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use `filter` versus `info`, `decide`, or `batch_decide`. The wording implies a conservative filtering use case, but it does not state prerequisites, exclusions, or conditions that would route an agent to this tool instead of a sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
infoARead-onlyIdempotent
Report server, resident backend, model, platform, limits, and metrics.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| model | Yes | |
| backend | Yes | |
| metrics | Yes | |
| version | Yes | |
| platform | Yes | |
| capabilities | Yes | |
| compute_units | Yes | |
| python_version | Yes | |
| backend_version | Yes | |
| initialization_state | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, fully covering the safety profile. The description adds a list of reported topics but does not disclose additional behavioral traits such as authentication requirements, rate limits, or potential side effects. Given the strong annotation coverage, the additional value is moderate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the verb 'Report', and each listed item is essential. There is no filler, and the list of reportable content is compact yet descriptive.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (no parameters) and has an output schema that will document return values. The description covers the main categories of information, which is sufficient for an agent to invoke it correctly. There is no missing context that would lead to misuse.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and 100% schema coverage (empty properties). Per rubric, missing parameter documentation is excused when there are no parameters. The description correctly focuses on the output categories rather than parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Report' and enumerates the resources (server, backend, model, platform, limits, metrics). This clearly differentiates it from sibling tools like decide, batch_decide, and filter, which focus on decision-making rather than environment information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The purpose clearly implies usage when the agent needs environment or runtime information. However, there is no explicit guidance about when to use this tool versus alternatives, nor any exclusion criteria. The context is clear but left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
batch_decide - First observed
decide - First observed
filter - First observed
info
TDQS
Scored across 4 tools
decide and batch_decide are clearly the single-item and batch variants of the same operation, while filter is a distinct conservative retention workflow. An agent might briefly hesitate between filter and repeated decide calls for relevance tasks, but the descriptions make each tool's purpose specific enough to avoid serious ambiguity.
Most names are short, lowercase, action-oriented commands: info, decide, filter. batch_decide is the main deviation because it introduces an underscore and a compound form, but the naming remains readable and the relationship to decide is obvious.
Four tools is well-scoped for this server's purpose: server introspection, single decisions, batched decisions, and candidate filtering. Each tool covers a distinct core workflow without redundancy or unnecessary surface area.
The tool surface covers the full apparent workflow: checking server state and limits, making a single bounded decision, making batched decisions, and conservatively filtering candidates. Escalation is intentionally left to the caller, so there are no obvious dead ends or missing operations.
Maintenance
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Governed data discovery, exact queries, decisions, simulations, and runtime utilities over MCP.
A paid remote MCP for Equibles, built to return verdicts, receipts, usage logs, and audit-ready JSON
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables running MCP tools against local MLX models on your Mac, with hardware-aware configuration, CLI streaming, and a dashboard for routing and monitoring.1,953 npm-
- AlicenseNot gradedqualityDmaintenanceMCP server that enables local Apple on-device Foundation Model access via any MCP client, supporting text generation, structured output, and multi-turn chat on macOS.2MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP hosts to query Jev's typed decision model—yes/no, choice, and score—with calibrated probabilities, while defaulting to an offline mock and disclosing all egress unless explicitly enabled.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables coding agents to make confident decisions using calibrated probabilistic tools for screening, verification, ranking, classification, and gating, fully self-hosted as an optional MCP server.MIT