Install
$ agentstack add mcp-mathissdupont-ingot ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Ingot
[](https://github.com/mathissdupont/ingot/actions/workflows/ci.yml) [](https://github.com/mathissdupont/ingot/releases) [](LICENSE)
An agent's permissions, its budget and its behaviour — checked before it runs, and enforced while it does.
Ingot compiles a small declarative language to Agent IR: a portable artifact that states what an agent may reach, what it will cost at most, and what it produces. It is a compiler and a toolchain, not a framework and not a runtime.
The point is what it refuses:
$ ingot check
error[ING4007]: `web.search` requires the `network` effect, which no policy rule grants
--> main.ing:31:12
|
31 | hits = call web.search(topic)
| ^^^^^^^^^^^^^^^^^^^^^^ needs `network`
|
= note: Ingot is default-deny: an effect with no rule is denied
= help: add `network allow [...]` to the agent's `policy` block
That is not a lint. network allow ["arxiv.org"] is checked against every call at compile time — and then enforced at run time, by a filtering proxy on a container network with no other route out. A tool server that ignores the proxy reaches nothing, rather than reaching everything.
Thirty seconds, and no API key
cargo install ingot-cli
# or download a binary: https://github.com/mathissdupont/ingot/releases
ingot init hello && cd hello
ingot check # types, effects, policy, budgets
ingot run --provider replay --input topic="compiler design" # prints a real artifact
A new project ships with a recorded fixture, so that last command produces an answer without contacting anything. Point it at a live model when you want one:
export ANTHROPIC_API_KEY=… # or OPENAI_API_KEY, or GEMINI_API_KEY
ingot run --input topic="compiler design"
And ingot studio puts the whole thing on one page — every project, what compiles, what it may reach, and every run it has had.
Deliberately not a general-purpose language
Ingot has no unbounded loops and no recursion between agents. That is the feature rather than a gap waiting to be filled.
`budget { steps ("Write about ${topic} as ${framing}.")
The answer is an ordinary `string` the flow reads. Two things keep that from
costing what it usually costs:
**It is an effect.** `consult` needs `human allow` in the policy, so **"can this
artifact run unattended?" is a question you answer by reading it** rather than by
starting it and finding out. CI denies `human`, and an artifact that needs a
person fails at the gate naming the question instead of hanging on a pipe.
**It is recorded.** A person is a third source of answers, beside the model and
the tools — recorded in its own list and replayed the same way, so an agent with
a human in it still has an offline test:
```bash
ingot run . --record tests/cassettes/framing.json --approvals stdin --events json
ingot run . --provider replay --cassette tests/cassettes/framing.json # asks nobody
Change the question and the replay refuses, exactly as an edited prompt does — and the message says re-recording means asking somebody again, rather than implying it is free. --yes approves gates and cannot answer a question: there is no safe side to guess.
The same channel carries an approval, so ingot studio can run an agent that needs a person — one gate at a time, with the effect and the reason shown before anything happens. See [RFC-0020](rfcs/0020-a-person-in-the-loop.md).
What a checked artifact is for
Because the artifact states its capabilities, its ceiling and its identity in a machine-readable form, something other than a person can decide about it — a scheduler, a queue, a marketplace, a contract:
| The question | Where the answer is | |---|---| | What will this agent do? | the flow and outputs in the Agent IR | | What may it touch? | the policy block — with values, default-deny, enforced | | What will it cost, at most? | budget { tokens, cost }, checked at compile time | | Is this the same agent I agreed to? | the OCI package's reproducible digest | | Did it do what it said? | the run record — the event stream, byte-identical on replay |
"At most $5" is a number you have before the run, not a bill afterwards. That is not something a faster language gives you.
What it is not
Ingot deliberately does not reimplement the layers that already exist:
| Concern | Ingot's position | |---------|------------------| | Tool protocol | MCP. No new tool protocol. | | Agent-to-agent messaging | A2A. No new messaging protocol. | | Distribution | OCI registries. No new registry. | | General execution | Existing runtimes, through backends. | | Sandboxing | Ours — the policy block, enforced. See [ADR-0006](docs/adr/0006-a-policy-enforcing-runner.md). |
The language remains the product surface. Templates, editor support and model assistance all create or edit ordinary .ing; the compiler, cassette tests, policy-derived containers and backends form one product loop around that source. See [RFC-0007](rfcs/0007-the-ingot-product-loop.md).
The one place Ingot builds its own execution machinery is the last row, and the scope there is narrow on purpose: a policy-enforcing runner, not a general execution engine. [docs/vision.md](docs/vision.md) is the full picture.
Status: pre-1.0 and moving. The compiler front end is complete, a reference interpreter runs Agent IR against Anthropic, OpenAI and Gemini, a second backend emits self-contained Python 3, the policy block is enforced by a real container boundary, and an agent can put a question to a person and read the answer without giving up a reproducible run. The language, the Agent IR and the artifact format can still change between releases. The [gap register](docs/gaps.md) lists every known limitation; the [changelog](CHANGELOG.md) says what landed when.
An example
language 0.1
package heptapus.examples.research
type search_result {
title: string
url: string
snippet: string
}
tool web.search(query: string) -> search_result[] !network
verifier CitationCheck(draft: markdown, min_sources: int)
/// A realistic research workflow.
agent ResearchAgent(topic: string) -> report {
model requires {
tool_calling
structured_output
context >= 128k
}
tools {
mcp web.search
}
budget {
steps ("Create diverse research queries for: ${topic}")
sources = parallel map queries as query {
call web.search(query)
}
draft = ask("Produce a source-grounded report.", context: sources)
verify CitationCheck(draft, min_sources: 8)
emit report = draft
}
}
Four complete examples live in [examples/](examples/).
Install
With cargo
Requires a stable Rust toolchain (MSRV 1.85).
cargo install ingot-cli # the `ingot` binary
cargo install ingot-mcp # `ingot-mcp-fs`, the reference tool server
cargo install ingot-lsp # the language server
Three crates rather than one because they are three permissions to grant a machine: a compiler, a process that reads your filesystem on an agent's behalf, and something an editor starts. Installing the first does not install the others.
To track main instead of a release:
cargo install --git https://github.com/mathissdupont/ingot ingot-cli
A prebuilt archive
Each release carries ingot, ingot-mcp-fs and ingot-lsp for Linux, macOS (Intel and Apple silicon) and Windows. Download the archive for your platform from Releases, verify it, and put the binaries on your PATH:
sha256sum -c SHA256SUMS --ignore-missing
tar -xzf ingot-*-x86_64-unknown-linux-gnu.tar.gz
Pre-1.0: the language, the Agent IR and the artifact format may change between releases.
From source
Requires a stable Rust toolchain (MSRV 1.85).
git clone https://github.com/mathissdupont/ingot
cd ingot
cargo build --release
./target/release/ingot --help
On Windows, if the repository sits inside a synced folder such as OneDrive, put the build directory elsewhere — synchronisation and target/ interact badly:
export CARGO_TARGET_DIR=/c/build/ingot
Commands
| Command | Purpose | |---------|---------| | ingot init [--template brief\|document-workflow] | create a tested starter project | | ingot new [--out-dir dir] "workflow words..." | create a compiler-verified project from a workflow description | | ingot new --provider auto "workflow words..." | the same, with a model writing the source and the compiler verifying it | | ingot new --project dir --provider auto "what to change" [--apply] | propose a source diff for an existing project; writes nothing without --apply | | ingot new --previous old.ing --candidate proposed.ing [--repair-candidate fixed.ing] | review model-proposed source, run bounded compiler repair and separate policy requests | | ingot check | parse, type-check, validate policy and budgets | | ingot fmt [--check] | canonical formatting | | ingot build [--target ir\|python] [--out-dir] | compile to Agent IR or self-contained Python 3 | | ingot package [--report python] [--out-dir] | write the checked artifact as an OCI package with a lockfile and a reproducible digest | | ingot package --verify | report every source, agent and field that moved since the package was written | | ingot ir [--agent] | print the IR to stdout | | ingot run [--input k=v] | execute the agent | | ingot run --sandbox | execute it with each tool server inside a boundary | | ingot run --contained | execute the agent itself inside a boundary | | ingot run --approvals stdin --events json | let whatever started the run answer its gates and questions, one at a time | | ingot image build [SOURCE] | build the version-matched local image used by contained runs | | ingot test | replay recorded cassettes, tool results included | | ingot doctor [--json] | report source, provider, MCP and container readiness without starting them | | ingot dev [--run] | watch source, check and build good revisions, optionally run them | | ingot tools [--json] [--propose] | discover, preflight and propose MCP tool declarations/routes | | ingot sandbox | show the boundary each tool server would run inside | | ingot studio | serve the local surface: projects, run history, and what this machine can reach | | ingot explain | explain a diagnostic in full |
Exit codes: 0 success, 1 the program has blocking diagnostics, 2 the command itself failed. Diagnostics, progress events and status lines go to stderr; ingot ir and ingot run write only their payload to stdout, so both are safe to pipe.
How it fits together
main.ing
│
▼
lexer → parser → AST ingot-lexer, ingot-parser, ingot-syntax
│
▼
name resolution → types → effects/policy ingot-semantic, ingot-lang-types
│
▼
lowering ingot-compiler
│
▼
Agent IR (canonical JSON) ingot-ir
│
┌─────┴──────────┐
▼ ▼
interpreter Python backend ingot-runtime, ingot-backend-python
│ │
▼ ▼
execution portability report implemented: M5
│
▼
MCP servers (stdio) ingot-mcp
With --sandbox the MCP servers move inside a policy-derived boundary (ingot-sandbox). With --contained the interpreter moves in with them, and ingot-supervisor is the channel it reaches the model and the operator through.
| Crate | Responsibility | |-------|----------------| | ingot-source | files, spans, line/column resolution | | ingot-diagnostics | diagnostic model, stable codes, terminal renderer | | ingot-lexer | tokens; never fails, always resynchronises | | ingot-syntax | AST and the canonical printer behind ingot fmt | | ingot-parser | recursive descent with error recovery | | ingot-lang-types | types, effects, policy subjects and decisions | | ingot-semantic | resolution, type checking, effect and policy analysis | | ingot-ir | the Agent IR model and its canonical encoding | | ingot-compiler | the driver and lowering | | ingot-runtime | the reference interpreter, providers and cassettes | | ingot-backend-python | self-contained Python 3 emission and portability reports | | ingot-language-service | editor-neutral diagnostics, formatting, completion, hover and definition over the compiler | | ingot-lsp | stdio language server adapter for editor diagnostics, formatting and navigation | | ingot-mcp | the MCP tool host, and the ingot-mcp-fs reference server | | ingot-sandbox | a policy block turned into a container boundary | | ingot-egress | the host-filtering proxy a bounded server's traffic leaves through | | ingot-supervisor | the channel between a contained run and the host serving it | | ingot-studio | the loopback server and single page behind ingot studio; holds no compiler, so it can show only what the CLI computed | | ingot-cli | the ingot binary |
Documentation
Start here:
- [Getting started](docs/guide/getting-started.md) — install, a project, an
offline run, a live one, tools, the boundary, and shipping it.
- [The language](docs/guide/the-language.md) — a tour of every construct, in
one example that grows. Each snippet is compiled by the test suite.
- [The toolchain](docs/guide/the-toolchain.md) — every command in the loop:
what it is for, what it refuses, and why.
Specifications
Each version is normative for what it defines and inherits the one before it.
- [Language 0.3](specs/language/v0.3.md) —
consultand thehumaneffect - [Language 0.2](specs/language/v0.2.md) — imports, optionals and unions, pure
helpers, a capability's reach, verifier bodies, persistent memory
- [Language 0.1](specs/language/v0.1.md) — syntax and static semantics
- [Agent IR 0.3](specs/ir/v0.3.md) — the
consultnode and thehumaneffect - [Agent IR 0.2](specs/ir/v0.2.md) — portable node source spans,
verifyconditions - [Agent IR 0.1](specs/ir/v0.1.md) — the original backend contract
- [Runtime 0.5](specs/runtime/v0.5.md) — resumption and persistent memory
- [Runtime 0.4](specs/runtime/v0.4.md) — what a
verifydoes, and what a failure ends - [Runtime 0.3](specs/runtime/v0.3.md) — streaming
- [Runtime 0.2](specs/runtime/v0.2.md) — the run record
- [Runtime 0.1](specs/runtime/v0.1.md) — what executing an artifact means
- [MCP binding 0.2](specs/tools/mcp-v0.2.md) — how a declared tool is served
- [
agent-ir.schema.json](specs/ir/agent-ir.schema.json) — machine-readable schema - [Vision](docs/vision.md) — what the project is for, and where it is going
- [Architecture](docs/architecture/overview.md) — how the phases fit together
- [Language service](docs/language-service.md) — editor-facing diagnostics, formatting, completion and navigation
- [Decision records](docs/adr/) — why the load-bearing choices were made
- [Gap register](docs/gaps.md) — every known limitation, with an identifier
Roadmap
| Milestone | Scope | State | |-----------|-------|-------| | M0 | scope, prior art, non-goals | done | | M1 | grammar, parser, diagnostics, formatter | done | | M2 | types, effects, policy, budgets, Agent IR | done | | M3 | reference interpreter, ingot run, end-to-end execution | done | | M4 | cassette record and replay, ingot test, MCP tool host | done | | M5 | a second backend and the portability report | done | | M6 | OCI artifact, lockfile, reproducible digest | done | | M7 | language server and editor support | done | | M8 | conformance suite and backend author guide | done | | M9 | Ingot Containers — the policy block as an enforced boundary | done | | M10 | ingot new — authoring with a model, verified by the
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mathissdupont
- Source: mathissdupont/ingot
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.