{
  "markdown": "<!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->\n\n<p align=\"center\">\n  <img src=\"https://cloudcdn.pro/noyalib/v1/logos/noyalib.svg\" alt=\"Noyalib logo\" width=\"128\" />\n</p>\n\n<h1 align=\"center\">noyalib-mcp</h1>\n\n<p align=\"center\">\n  <strong>Model Context Protocol server exposing noyalib's\n  lossless YAML editing to AI agents (Claude Desktop, Claude\n  Code, Cursor, Zed, Continue.dev, …).</strong>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/sebastienrousseau/noyalib-mcp/actions\"><img src=\"https://img.shields.io/github/actions/workflow/status/sebastienrousseau/noyalib-mcp/ci.yml?style=for-the-badge&logo=github\" alt=\"Build\" /></a>\n  <a href=\"https://crates.io/crates/noyalib-mcp\"><img src=\"https://img.shields.io/crates/v/noyalib-mcp.svg?style=for-the-badge&color=fc8d62&logo=rust\" alt=\"Crates.io\" /></a>\n  <a href=\"https://docs.rs/noyalib-mcp\"><img src=\"https://img.shields.io/badge/docs.rs-noyalib--mcp-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs\" alt=\"Docs.rs\" /></a>\n  <a href=\"https://lib.rs/crates/noyalib-mcp\"><img src=\"https://img.shields.io/badge/lib.rs-noyalib-orange.svg?style=for-the-badge\" alt=\"lib.rs\" /></a>\n  <a href=\"https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/noyalib-mcp\"><img src=\"https://img.shields.io/ossf-scorecard/github.com/sebastienrousseau/noyalib-mcp?style=for-the-badge&label=OpenSSF%20Scorecard&logo=openssf\" alt=\"OpenSSF Scorecard\" /></a>\n  <a href=\"https://www.bestpractices.dev/projects/14496\"><img src=\"https://img.shields.io/cii/level/14496?style=for-the-badge&label=OpenSSF%20Best%20Practices&logo=openssf\" alt=\"OpenSSF Best Practices\" /></a>\n</p>\n\n---\n\n## Contents\n\n- [Install](#install) — Cargo, npx, Docker\n- [Requirements](#requirements) — toolchain floor, platforms, the core pin\n- [Quick Start](#quick-start) — JSON-RPC handshake\n- [Why this approach?](#why-this-approach) — design rationale\n- [Connect](#connect) — per-client configuration\n- [Tools](#tools) — MCP tool reference\n- [Examples](#examples) — runnable scripts\n- [Verification](#verification) — cosign + npm provenance\n- [When not to use noyalib-mcp](#when-not-to-use-noyalib-mcp)\n- [Documentation](#documentation)\n- [License](#license)\n\n---\n\n## Install\n\n```bash\ncargo install noyalib-mcp\n```\n\nFor environments without a Rust toolchain (the typical AI-agent\ndeployment shape):\n\n```bash\n# npm wrapper — auto-downloads the matching binary on first run,\n# caches under ~/.cache/noyalib-mcp/<version>/.\nnpx @sebastienrousseau/noyalib-mcp\n\n# Container — multi-arch (linux/amd64, linux/arm64).\ndocker run --rm -i ghcr.io/sebastienrousseau/noyalib-mcp:latest\n```\n\n> **Split from the monorepo since v0.0.13.** Prior versions\n> shipped from `sebastienrousseau/noyalib/crates/noyalib-mcp/`\n> under the workspace-lockstep release cadence. From v0.0.13\n> onward `noyalib-mcp` lives here as its own crate, still\n> released in strict lockstep with the parent\n> [`noyalib`](https://github.com/sebastienrousseau/noyalib) at\n> the same version. See\n> [ADR-0005](https://github.com/sebastienrousseau/noyalib/blob/main/docs/adr/0005-workspace-split.md)\n> for the rationale and rollback recipe.\n\nBoth consume the same signed binary attached to every GitHub\nRelease. See [Verification](#verification) for the verify\ncommands.\n\n---\n\n## Requirements\n\n- **Rust 1.86.0 or newer** to build from source: `rust-version` in\n  the manifest, enforced by the `msrv-core` CI job on every push.\n- **Any tier-1 platform.** CI runs the tests on Linux, macOS, and\n  Windows with the stable, beta, and nightly toolchains; stable is the\n  gate, beta and nightly are early warning.\n- **The matching core.** This crate pins `noyalib` at the identical\n  `=0.0.X` and releases in lockstep with it; Cargo resolves that pin\n  for you.\n- **An MCP client** speaking JSON-RPC 2.0 over stdio (2025-06-18 or\n  2026-07-28 protocol eras); the README's Connect section lists tested\n  hosts.\n\n## Quick Start\n\nThe server speaks JSON-RPC 2.0 over stdio with newline-delimited\nframes, per the\n[MCP specification](https://modelcontextprotocol.io). A typical\nagent launches the binary as a child process, sends\n`initialize`, then dispatches tool calls:\n\n```json\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":{},\"clientInfo\":{\"name\":\"agent\",\"version\":\"0.0.1\"}}}\n{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}\n{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}\n{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\n \"params\":{\"name\":\"format\",\"arguments\":{\"yaml\":\"a:1\\nb:2\\n\"}}}\n```\n\n---\n\n## Why this approach?\n\nAI agents that edit YAML configuration today regex-replace and\ncorrupt comments, indentation, and document structure. The same\nagent fixing a port number in a Kubernetes manifest can shift\nevery comment by a line, reorder sibling keys, or strip\ntrailing whitespace that a downstream linter cared about.\n\nnoyalib's CST does the edits losslessly — a `set(\"server.port\",\n\"9090\")` rewrites only the byte span of the `8080` scalar; the\nsurrounding comments and indentation pass through untouched.\nThis server is the protocol shim that lets MCP-aware clients\ndrive that engine safely:\n\n- **Lossless mutation.** `tools/call set` returns a document\n  byte-identical to the input outside the touched span.\n- **Surgical reads.** `tools/call get` walks the dotted path\n  and returns just the value, not the whole tree.\n- **Schema validation.** `tools/call validate --schema` runs\n  the same JSON Schema 2020-12 engine `noyavalidate` ships.\n- **Stdio transport.** Standard MCP. Works with every\n  spec-compliant client.\n\n---\n\n## Connect\n\n### Claude Desktop / Claude Code\n\n```bash\nclaude mcp add noyalib $(which noyalib-mcp)\n```\n\n### Cursor\n\n`~/.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"noyalib\": {\n      \"command\": \"noyalib-mcp\"\n    }\n  }\n}\n```\n\n### Zed\n\n`~/.config/zed/settings.json`:\n\n```json\n{\n  \"context_servers\": {\n    \"noyalib\": {\n      \"command\": { \"path\": \"noyalib-mcp\" }\n    }\n  }\n}\n```\n\n### Continue.dev\n\n`~/.continue/config.json`:\n\n```json\n{\n  \"experimental\": {\n    \"modelContextProtocolServers\": [\n      { \"transport\": { \"type\": \"stdio\", \"command\": \"noyalib-mcp\" } }\n    ]\n  }\n}\n```\n\n### Any other MCP-aware client\n\nPoint at the binary; the transport is stdio with newline-\ndelimited JSON-RPC 2.0.\n\n---\n\n## Tools\n\nThe v0.0.1 server registers two file-oriented tools — both\noperate on a YAML file at `file: <path>`, not on inline source\nstrings, so an agent's edits land on disk losslessly:\n\n- `noyalib_get` — Takes `{ file: string, path: string }`; returns the raw source fragment at the dotted/indexed path (e.g. `server.host`, `items[0].name`). No re-quoting; no canonicalisation.\n- `noyalib_set` — Takes `{ file: string, path: string, value: string }`; returns the file rewritten via the lossless CST so only the touched span changes; comments, blank lines, and sibling formatting survive byte-for-byte. The `value` is a YAML fragment (`0.0.2`, `\"hello\"`, `[1, 2, 3]`); a parse failure leaves the file unchanged.\n- `noyalib_parse` — Takes `{ yaml: string }`; returns the JSON data model of the text (tags stripped, a stream as an array). Stateless: nothing on disk is touched.\n- `noyalib_edit` — Takes `{ yaml: string, path: string, value: string }`; returns the whole text with that one value replaced losslessly. Stateless.\n- `noyalib_validate` — Takes `{ yaml: string, schema?: string }`; returns `valid` with either the parse error (line and column) or every JSON Schema violation with its path. Stateless.\n\nEach tool's full input schema lives in the response to\n`tools/list`. The server also handles the standard\n`initialize` / `initialized` / `notifications/cancelled`\nlifecycle.\n\nFormat / parse / validate are not exposed as MCP tools today —\nthey're available via the [`noya-cli`](../noya-cli/README.md)\nbinaries (`noyafmt`, `noyavalidate`) and the\n[`noyalib`](../noyalib/README.md) library API. Promotion to\nfirst-class MCP tools is on the v0.0.2+ roadmap.\n\n---\n\n## Examples\n\nAgent-driving demos under\n[`crates/noyalib-mcp/examples/`](examples/):\n\n| Script | What it shows |\n|---|---|\n| [`handshake.sh`](examples/handshake.sh) | `initialize` → `tools/list` smoke test. Confirms the binary speaks the protocol and announces the expected tools. |\n| [`format-call.sh`](examples/format-call.sh) | `tools/call format` on a poorly-spaced document. Demonstrates that comments + indentation pass through the CST formatter unchanged. |\n| [`set-then-get.sh`](examples/set-then-get.sh) | Round-trip the mutation surface: `set` rewrites `server.port`, `get` reads it back. Surgical edit; surrounding bytes untouched. |\n\n```bash\nchmod +x crates/noyalib-mcp/examples/*.sh\ncrates/noyalib-mcp/examples/handshake.sh | jq -c .\n```\n\nPOSIX-shell only — no `jq`, no `node` dependencies. Pipe\nthrough `jq -c .` if you want pretty-printed JSON responses.\n\n---\n\n## Verification\n\nGitHub Releases ship the crate archive and a CycloneDX SBOM,\neach with a sigstore bundle and checksums; the GHCR image is\nbuilt from the tagged source. Pre-built binaries are not\nattached to releases yet. To verify a release artefact:\n\n```bash\nCOSIGN_EXPERIMENTAL=1 cosign verify-blob \\\n  --certificate-identity-regexp 'https://github.com/sebastienrousseau/noyalib-mcp/' \\\n  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \\\n  --bundle <artefact>.bundle \\\n  <artefact>\n```\n\nThe npm wrapper additionally carries an\n[npm provenance attestation](https://docs.npmjs.com/generating-provenance-statements):\n\n```bash\nnpm view noyalib-mcp provenance\n```\n\nFull cookbook: [`pkg/VERIFY.md`](https://github.com/sebastienrousseau/noyalib/blob/main/pkg/VERIFY.md).\n\n---\n\n## When not to use noyalib-mcp\n\n- **You don't trust your AI agent with filesystem access at\n  all.** noyalib-mcp doesn't read or write files itself —\n  every operation takes the YAML document as a string argument\n  and returns the result as a string. The agent decides what\n  to do with the result. If the agent has filesystem access,\n  it can persist the response wherever it wants.\n- **You need a sandboxed schema registry.** noyalib-mcp accepts\n  schemas as inline strings in `tools/call validate`; it does\n  not fetch schemas from URLs. If your workflow needs\n  network-resolved schemas, the agent is responsible for\n  fetching the schema first and passing the bytes.\n\n---\n\n## Compatibility\n\n**MSRV: Rust 1.86.0** stable — the lowest toolchain this crate\ncan be **built and tested** on, matching the `noyalib` core floor.\n`criterion 0.8` (the benchmark dev-dependency) declares\n`rust-version = 1.86`, so `cargo check --all-targets` and the\nbench suite fail on 1.85 with `criterion@0.8.2 requires rustc\n1.86` — `cargo check --lib` alone still builds on 1.85. We publish\nthe number we verify. The MCP wire surface itself is text-only\nJSON-RPC and pulls no nightly-only deps. CI verifies the floor on every\nPR via the `Per-crate MSRV` workflow job. The bump policy\nlives in\n[`docs/POLICIES.md`](https://github.com/sebastienrousseau/noyalib/blob/main/docs/POLICIES.md#1-msrv-minimum-supported-rust-version).\n\n**Tier-1 platforms** (CI-verified each PR): `aarch64-apple-darwin`,\n`x86_64-unknown-linux-gnu`, `x86_64-pc-windows-msvc`. The\nbinary writes via atomic file replacement on every platform —\non Windows via `MoveFileExW(MOVEFILE_REPLACE_EXISTING |\nMOVEFILE_WRITE_THROUGH)` semantics.\n\n---\n\n## Documentation\n\nThe four entry points, identical across every repo in the family:\n\n- **[User Manual](https://sebastienrousseau.github.io/noyalib-mcp/manual/)** — this crate's rendered book: its guides, architecture, and release notes; the family manual for the core library is at [https://sebastienrousseau.github.io/noyalib/manual/](https://sebastienrousseau.github.io/noyalib/manual/)\n- **[API reference](https://docs.rs/noyalib-mcp)** — rustdoc on docs.rs\n- **[Developer docs](DEVELOPMENT.md)** — this repo's dev entry point, pointing at the family guide\n- **[Ecosystem map](https://github.com/sebastienrousseau/noyalib/blob/main/docs/ECOSYSTEM.md)** — the six crates, the lockstep model, the scorecard\n\n- **Engineering policies** (MSRV, SemVer, security, performance, concurrency, platform support, feature flags):\n  [`docs/POLICIES.md`](https://github.com/sebastienrousseau/noyalib/blob/main/docs/POLICIES.md)\n- **Security policy**:\n  [`SECURITY.md`](https://github.com/sebastienrousseau/noyalib/blob/main/SECURITY.md)\n- **API reference**: <https://docs.rs/noyalib-mcp>\n- **Tools reference (input schemas + error codes)**:\n  [`docs/tools-reference.md`](docs/tools-reference.md)\n- **Agent integration (Claude Desktop, Cursor, Continue.dev)**:\n  [`docs/agent-integration.md`](docs/agent-integration.md)\n- **MCP specification**: <https://modelcontextprotocol.io>\n- **Workspace README**:\n  <https://github.com/sebastienrousseau/noyalib#readme>\n\n---\n\n## Related MCP Servers\n\nSibling MCP servers by the same author — open-source, Apache-2.0 licensed, targeting banking and financial-services AI agents. `noyalib-mcp` complements them by giving agents lossless YAML editing for structured configuration files:\n\n| Server | Purpose |\n|---|---|\n| [`pain001-mcp`](https://github.com/sebastienrousseau/pain001-mcp) | Generate & validate ISO 20022 pain.001 payment initiation files (Customer Credit Transfer) |\n| [`bankstatementparser-mcp`](https://github.com/sebastienrousseau/bankstatementparser-mcp) | Parse bank statements (BAI2, MT940/MT942, CAMT.053, OFX, CSV) into structured transactions |\n| [`camt053-mcp`](https://github.com/sebastienrousseau/camt053-mcp) | Parse & reconcile ISO 20022 camt.053 bank-to-customer statements — CBPR+/HVPS+ ready |\n| [`acmt001-mcp`](https://github.com/sebastienrousseau/acmt001-mcp) | Generate & validate ISO 20022 acmt.001 account management messages |\n\n---\n\n## MCP Registry\n\n`mcp-name: io.github.sebastienrousseau/noyalib-mcp`\n\n---\n\n## Conformance\n\nEvery push runs the official [yaml-test-suite](https://github.com/yaml/yaml-test-suite)\nthrough this server's tools, from the same vendored suite and the same core\ncommit as the `noyalib` core: 195 of 195 addressable cases (the other 211 have\nno top-level key for `noyalib_get` to read; `noyalib_parse` sees all of them).\nA two-document configuration that uses most of YAML at once\n(`tests/fixtures/ultra-complex/`) parses to exactly its expected JSON through\n`noyalib_parse`. Details and the family table:\n[noyalib.com/conformance](https://noyalib.com/conformance/).\n\n## License\n\nDual-licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)\nor [MIT](https://opensource.org/licenses/MIT), at your option.\n",
  "bytes": 14517,
  "sha": "da777843bb52cc71cda84d56360abb8acc15ce1fea314f2e7c9b478b4627c18f",
  "repo_slug": "sebastienrousseau/noyalib-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_sebastienrousseau_noyalib_mcp_5cf3ae33/readme"
}