FIDE Laws of Chess

Official registry Games, sports and entertainment

FIDE Laws of Chess (2023) as an executable model: arbiter cases, answers with rules and judgments

Install

Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).

Remote (streamable-http)
Claude Code
claude mcp add --transport http fide-laws-of-chess 'https://mcp.arxo.io/mcp/fide-chess'
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "fide-laws-of-chess": {
            "type": "http",
            "url": "https://mcp.arxo.io/mcp/fide-chess"
        }
    }
}
NPM package @arxo/mcp-fide-chess
Claude Code
claude mcp add fide-laws-of-chess -e 'FIDE_CHESS_MCP_CALL_TIMEOUT=<FIDE_CHESS_MCP_CALL_TIMEOUT>' -- npx -y @arxo/mcp-fide-chess@0.1.1
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "fide-laws-of-chess": {
            "command": "npx",
            "args": [
                "-y",
                "@arxo/mcp-fide-chess@0.1.1"
            ],
            "env": {
                "FIDE_CHESS_MCP_CALL_TIMEOUT": "<FIDE_CHESS_MCP_CALL_TIMEOUT>"
            }
        }
    }
}

Environment variables

  • FIDE_CHESS_MCP_CALL_TIMEOUT Per-call timeout in seconds for the local host (optional)

Documentation

From the project's README on GitHub, refreshed weekly. Links open on GitHub.

Contents
  1. FIDE Laws of Chess on Arxo
  2. Start in Node.js
  3. Use as an MCP server
  4. Choose a case
  5. Facts and arbiter judgments
  6. Inspect the evidence
  7. Model and loader API
  8. Formalization depth
  9. Scope and verification
  10. Source pins and reproduction

FIDE Laws of Chess on Arxo

Explore a chess arbiter's decision through a pinned model, explicit facts and an inspectable answer. Ten retained fictional cases cover illegal moves, flag fall, rapid/blitz exceptions, recording and arbiter judgment.

Node.js 20+ · ESM · canon package 0.1.0 · model 0.1.1 · FIDE edition effective 1 January 2023

Start in Node.js · Cases · Evidence · Depth · Submit a case · Source repository

This is an independent open-source teaching and research demonstration. For an actual chess ruling, use the authentic FIDE Laws and the competent arbiter. Source text and model scope are pinned; the package does not claim general chess-engine capability or complete formalization.

Start in Node.js

Requirements: Node.js 20+. The example uses ES modules; keep the .mjs extension. This recipe was checked on macOS arm64 with Node.js 20.20.2 on 14 October 2026. No global CLI, Git clone or MCP client is needed for this route.

Create a fresh directory, open a terminal there, then run:

npm init -y
npm install --ignore-scripts @arxo/canon-fide-chess@0.1.0 @arxo/law@0.4.3

Save this as example.mjs, then run node example.mjs:

import { open } from '@arxo/law';
import { loadModel } from '@arxo/canon-fide-chess/chess';
import { game, white, getCaseInput } from '@arxo/canon-fide-chess/examples/arbiter';

const model = await loadModel();
const chess = await open(model.spec, {
  offline: true,
  local: { packages: { [model.spec]: model.package } },
});

const input = getCaseInput('SecondIllegal');
const loss = await chess.truth('game_lost_by', [game, white], input);
const draw = await chess.truth('game_drawn', [game], input);
console.log(loss.evaluationStatus, loss.truthStatus); // COMPUTED, TRUE_ONLY
console.log(draw.evaluationStatus, draw.truthStatus); // COMPUTED, NEITHER

The two output lines are loss, then draw:

COMPUTED TRUE_ONLY
COMPUTED NEITHER

COMPUTED means the query was evaluated. TRUE_ONLY means it has positive support and no negative support. NEITHER means neither polarity is supported; it does not establish that the proposition is false.

Now replace only getCaseInput('SecondIllegal') with getCaseInput('SecondIllegalNoMate') and run node example.mjs again:

REQUIRES_JUDGMENT NEITHER
COMPUTED TRUE_ONLY

The second line now establishes a draw. This case supplies the fact that the opponent cannot checkmate by any legal series. The separate loss query still requests an arbiter's assessment because other reachable loss grounds remain unresolved. Read both status fields; REQUIRES_JUDGMENT identifies an assessment the model does not decide on its own.

To try another retained episode, choose a name from the case table. To propose your own episode, open an issue with the case facts, legal date, query, package/runtime versions, output and the FIDE clause or model rule you think should give a different answer. Use a fictional or anonymized case.

The SDK executes the rules through @arxo/law-engine@0.5.3. Installation alone does not register this distribution in the SDK's automatic canon resolver: keep the explicit local.packages handoff above. The loader implements no chess decisions or formulas.

Use as an MCP server

The separate native MCP wrapper runs the same pinned model over stdio:

npx -y @arxo/mcp-fide-chess@0.1.0

Node.js 20+, Linux x64 or macOS arm64. Client configuration, HTTP endpoint, inputs and limitations · OCI recipe · npm recipe · Accepted delivery. This MCP delivery is separate from the Node.js route above.

Choose a case

getCaseInput(name)EpisodeChecked question and result
TouchIntentUnknownA movable own piece; intentional touch not adjudicatedmust_move_first_touched_piece: REQUIRES_JUDGMENT / NEITHER
FirstIllegalOne completed illegal moveLoss: REQUIRES_JUDGMENT / NEITHER; draw: COMPUTED / NEITHER
SecondIllegalTwo illegal moves under the model's specified closureLoss: COMPUTED / TRUE_ONLY
SecondIllegalNoMateTwo illegal moves; inability to checkmate establishedDraw: COMPUTED / TRUE_ONLY
FlagFallFlag observed, time control not completed, mate possibleLoss: COMPUTED / TRUE_ONLY
FlagFallNoMateThe same flag; inability to checkmate establishedDraw: COMPUTED / TRUE_ONLY
RapidFirstIllegalRapid 15+10; first illegal moveOpponent receives 60 seconds; 120-second query is NEITHER
BlitzFirstIllegalCompetitiveBlitz 3+2 under competitive rules B.2Opponent receives 120 seconds; 60-second query is NEITHER
ShortOfTimeRecordingStandard chess, no increment, 240 seconds leftmust_record_moves: COMPUTED / FALSE_ONLY
DeviceWarningElectronic device evident; arbiter gave a warningLoss and differing-penalty queries: COMPUTED / TRUE_ONLY

All 18 original case/query expectations are retained and checked. The fixture export provides caseNames, game, white, black, king, CaseName and getCaseInput(name). Each call returns an independent copy; an unknown name throws RangeError.

Facts and arbiter judgments

getCaseInput preserves the CLI's canonical assertions, constants, context and options. The loader supplies neither absent facts nor adjudications. The model's explicitly declared closures are part of its rules; they are not a general assumption that a missing fact is false.

For touch-move, use the two declared arguments — player and piece:

import { open } from '@arxo/law';
import { loadModel } from '@arxo/canon-fide-chess/chess';
import { white, king, getCaseInput } from '@arxo/canon-fide-chess/examples/arbiter';

const model = await loadModel();
const chess = await open(model.spec, {
  offline: true, local: { packages: { [model.spec]: model.package } },
});
const answer = await chess.truth(
  'must_move_first_touched_piece', [white, king], getCaseInput('TouchIntentUnknown'),
);
const document = JSON.parse(new TextDecoder().decode(answer.document));
console.log(answer.evaluationStatus, answer.truthStatus); // REQUIRES_JUDGMENT, NEITHER
console.log(document.results[0].judgmentRequests);

A positive, explicitly adjudicated intentional-touch assertion establishes this model's obligation; that path is checked separately. The original missing-judgment fixture stays unchanged.

Missing empirical facts, negative facts and contradictory support retain NEITHER, FALSE_ONLY and BOTH. For the checked empirical conflict, SDK 0.4.3 returns COMPUTED / BOTH: the query was computed and both polarities are supported. Read both fields; do not collapse them to a Boolean. Exact Decimal inputs, such as recorded points, are strings ('0.75').

Complete canonical input for SecondIllegal

{
  "legalTime": "2023-06-01",
  "assertions": [
    {
      "contentHash": "sha256:696ba690ec316ad1654c94c94886b3d6e9764573460a0ed89f76280496c904fa",
      "evidence": [],
      "id": "urn:law:examples:chess:arbiter#player",
      "kind": "assertion",
      "literal": {
        "args": [
          {
            "id": "urn:example:chess:game",
            "kind": "entity_ref"
          },
          {
            "id": "urn:example:chess:white",
            "kind": "entity_ref"
          }
        ],
        "kind": "literal",
        "polarity": "positive",
        "predicate": "urn:fide:laws:clir:chess#player_of"
      },
      "origin": "case_input",
      "package": "urn:law:examples:chess:arbiter"
    },
    {
      "contentHash": "sha256:9f7706ed8482cd04f869afdd849b90eea3c2e42ca246bf932c8a20f77a1fcc15",
      "evidence": [],
      "id": "urn:law:examples:chess:arbiter#complete-mate-facts",
      "kind": "assertion",
      "literal": {
        "args": [
          {
            "id": "urn:example:chess:white",
            "kind": "entity_ref"
          }
        ],
        "kind": "literal",
        "polarity": "positive",
        "predicate": "urn:fide:laws:clir:chess#checked_player"
      },
      "origin": "case_input",
      "package": "urn:law:examples:chess:arbiter"
    },
    {
      "contentHash": "sha256:cd688c83624c70688f10ead443e5c46c32ad7d3310696caf6dad9b80be7c1cb0",
      "evidence": [],
      "id": "urn:law:examples:chess:arbiter#illegal-count",
      "kind": "assertion",
      "literal": {
        "args": [
          {
            "id": "urn:example:chess:white",
            "kind": "entity_ref"
          },
          {
            "kind": "value",
            "type": {
              "name": "urn:law:std#Integer"
            },
            "value": 2
          }
        ],
        "kind": "literal",
        "polarity": "positive",
        "predicate": "urn:fide:laws:clir:chess#completed_illegal_move_count"
      },
      "origin": "case_input",
      "package": "urn:law:examples:chess:arbiter"
    }
  ],
  "context": {
    "decisionTime": "2026-09-08T12:00:00Z",
    "knowledgeTime": "2026-09-08T12:00:00Z",
    "legalTime": "2023-06-01",
    "timezone": "UTC"
  },
  "options": {}
}

This input was captured by released CLI 0.2.3 from the retained .lawcase; the fixture generator does not reproduce chess semantics. Fixture bytes · Capture provenance.

Inspect the evidence

Preserve answer.document as the canonical bytes returned by Arxo. With the same runtime version, pinned model and dependencies, repeated executions of identical complete inputs (query, facts, judgments, temporal context and options) reproduce those bytes and their hashes. answer.proof.nodes identifies the applied rules and their premises.

The current SDK's answer.sources and proof-node source-anchor arrays are empty for these queries. Source links below are an explicit static join of executed producer IDs with anchors in the hash-checked model; they are not additional citations emitted by the evaluator. The pinned publication is the FIDE Handbook, Laws 2023.

This complete example saves the loss answer and prints its model anchor links:

import { writeFile } from 'node:fs/promises';
import { open } from '@arxo/law';
import { loadModel } from '@arxo/canon-fide-chess/chess';
import { game, white, getCaseInput } from '@arxo/canon-fide-chess/examples/arbiter';

const model = await loadModel();
const chess = await open(model.spec, {
  offline: true, local: { packages: { [model.spec]: model.package } },
});
const answer = await chess.truth('game_lost_by', [game, white], getCaseInput('SecondIllegal'));
await writeFile('answer.json', answer.document);
const nodes = new Map(model.package.ir.nodes.map(node => [node.id, node]));
const sourceLinks = answer.proof.nodes.filter(node => node.rule).map(node => ({
  rule: node.rule,
  anchors: (nodes.get(node.rule)?.anchors ?? []).map(id => ({
    id, locator: nodes.get(id)?.locator,
  })),
}));
console.log(answer.hashes, sourceLinks); // includes SecondIllegalMoveLoses → article/7

What the model knows: native touch-move producer tree

Produced by chess.unfold('must_move_first_touched_piece', { depth: 2, lang: 'en', quote: 0 }), with no selected case. Complete native tree and text. Recursion depth is separate from formalization depth.

Model and loader API

ImportExact model specExports
@arxo/canon-fide-chessfide.laws.chess@0.1.1models, loadModel(exactSpec), error classes
@arxo/canon-fide-chess/chessfide.laws.chess@0.1.1spec, loadModel()
@arxo/canon-fide-chess/examples/arbiterRetained case inputsIdentifiers, case names and independent input copies

loadModel returns { spec, package, descriptor, pin, questionCatalog }. Root imports read only the catalog and metadata. A load verifies original bytes before parsing the selected world and its catalog, then returns an independent model object. The descriptor remains separate: package.meta.contentHash is the linked world hash; packageContentHash is the original package hash. There are no model imports in this release.

Unknown or versionless specs fail with ModelNotFoundError.code === 'MODEL_NOT_FOUND'. Missing, corrupt or inconsistent model assets fail with ModelIntegrityError.code === 'MODEL_INTEGRITY'. There is no network fallback. TypeScript declarations cover exact specs, relation names, qualified relation names and fixture names; argument arity and value kinds are validated by the SDK at runtime.

Formalization depth

ModelPinned editionMeasured unit / denominatorEXECUTABLEOther measured levelsStatus
fide.laws.chess@0.1.1Effective 1 January 2023en_article / 12 articles12INTERPRETED: 0, ANCHORED: 0, SOURCE_ONLY: 0, NONE: 0partial

The existing boundaries.depth measure reads own package nodes, excluding imports, and the original article-division declaration. All 12 articles have deriving rules; this coarse measure does not establish complete formalization of every clause. 28 anchor references remain unresolved by this article measure and are recorded in the report.

The preface and Appendices A–D are outside this denominator. A and B have executable rules used by the rapid/blitz cases; C's notation and D's organizational material are not executed by this demonstration. Guidelines are outside the retained Laws publication. These areas remain unmeasured by the article report.

Per-unit report records the denominator, edition, source/package/world hashes, original measurement implementation hashes and adapter hash. EXECUTABLE, source presence, completeness, declared scenarios and successful runs are separate claims. The model exposes institutional predicates and a procedure; it declares no deontic norms or full obligation-lifecycle positions.

Scope and verification

The package evaluates presented episodes. Most board/history conditions remain explicit protocol facts. Its limited observed-position slice handles complete known four-piece K/Q/R frames and a specific inability-to-mate case; other positions remain outside that slice. It does not establish general position reachability, parse PGN or construct a tournament pairing. Rating, title, tie-break and Swiss-pairing models are separate packages and are not bundled.

Model 0.1.1 corrects four preparation defects while preserving the original expected outcomes: scoped procedure predicates in the fixtures, and an exact Decimal intermediate before half-point rounding. The selected package passes 103 source scenarios, including six new numeric boundaries, through build, replay and rebuild. The installed demonstration checks all 18 retained questions, loader failures/isolation, explicit and absent judgment, missing/negative/conflicting facts, score boundaries, canonical repeatability, README examples and strict TypeScript.

Checks are addressed to this distribution. Full corpus: not_checked; releaseVerified: false. Delivery checks do not establish subject accuracy or completeness.

Source pins and reproduction

Source pin fixes original model/descriptor/world/catalog bytes and case inputs to an immutable public source revision. Source origin separately records the corpus origins and addressed fixes. English source text is a pinned visible-text extraction (PINNED_UNOFFICIAL_COPY), not a claimed official PDF publication. FIDE attribution and publisher terms are retained in NOTICE; Apache-2.0 covers Arxo-authored code and does not replace those terms.

To rebuild the wrapper from the pinned inputs in the repository:

git clone https://github.com/arxohq/arxo-fide-chess.git
cd arxo-fide-chess/npm
npm ci --ignore-scripts
npm run build -- --canon ..
npm test
npm run test:types
npm run candidate -- --out /absolute/new-candidate-directory

The candidate script prepares one local tarball and the existing arxo.npm-candidate/1 manifest; it does not publish. Delivery uses the established CI in arxo-io/law. Publishing and verification recipe · Delivery record.

Frequently asked questions

What is FIDE Laws of Chess?

FIDE Laws of Chess (2023) as an executable model: arbiter cases, answers with rules and judgments

How do I install FIDE Laws of Chess?

It runs as a remote server. In Claude Code: claude mcp add --transport http fide-laws-of-chess 'https://mcp.arxo.io/mcp/fide-chess'. For other clients, paste the JSON configuration from this page into their MCP settings.

Does FIDE Laws of Chess need an API key?

Its registry entry lists no required key or secret. Some features may still need an account with the service it connects to.

Is FIDE Laws of Chess open source?

Yes. Its code is on GitHub under the Apache-2.0 license.

Who maintains FIDE Laws of Chess?

It is published by arxohq. AI.tn lists it but does not maintain or endorse it.

From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.