io.github.FoodXDevelopment/foodblock-mcp

编码与调试

by foodxdevelopment

適用於任何 AI agent 的 food data 工具;以英文描述食物,即可回傳結構化資料。

什么是 io.github.FoodXDevelopment/foodblock-mcp

適用於任何 AI agent 的 food data 工具;以英文描述食物,即可回傳結構化資料。

README

FoodBlock

A content-addressable protocol for universal food data.

One axiom. Three fields. Six base types. Every food industry operation.

json
{
  "type": "substance.product",
  "state": { "name": "Sourdough", "price": 4.50, "allergens": { "gluten": true } },
  "refs": { "seller": "a1b2c3...", "inputs": ["flour_hash", "water_hash", "yeast_hash"] }
}

id = SHA-256(canonical(type + state + refs))

Why

The food industry spans 14 sectors — farming, processing, distribution, retail, hospitality, regulation, sustainability, and more. Every sector models food data differently. There is no shared primitive.

FoodBlock is that primitive. One data structure that can represent a farm harvest, a restaurant menu item, a food safety certification, a cold chain reading, a grocery order, or a consumer review. Same three fields. Same hashing. Same protocol.

The Primitive

Every FoodBlock has exactly three fields:

FieldTypeDescription
typestringWhat kind of block (dot-notated subtypes)
stateobjectThe block's data (schemaless, any valid JSON)
refsobjectNamed references to other blocks by hash

Identity is derived from content: SHA-256(canonical(type + state + refs)). Same content always produces the same hash, regardless of where or when the block is created.

Six Base Types

Entities — things that exist:

  • actor — farmer, restaurant, retailer, regulator, consumer, device
  • place — farm, factory, store, warehouse, kitchen, vehicle
  • substance — ingredient, product, meal, surplus, commodity

Actions — things that happen:

  • transform — cooking, milling, harvesting, fermenting, composting
  • transfer — sale, shipment, donation, booking, subscription
  • observe — review, certification, inspection, post, sensor reading

Subtypes via dot notation: actor.producer, substance.product, observe.review, transfer.order.

Install

bash
npm install foodblock

Quick Start — fb()

The fastest way to use FoodBlock. Describe food in plain English, get structured blocks back.

javascript
const { fb } = require('foodblock')

fb("Sourdough bread, $4.50, organic, contains gluten")
// => { type: 'substance.product', state: { name: 'Sourdough bread', price: { value: 4.5, unit: 'USD' }, organic: true, allergens: { gluten: true } }, blocks: [...] }

fb("Amazing pizza at Luigi's, 5 stars")
// => { type: 'observe.review', state: { name: "Luigi's", rating: 5, text: "..." }, blocks: [...] }

fb("Green Acres Farm, 200 acres, organic wheat in Oregon")
// => { type: 'actor.producer', state: { name: 'Green Acres Farm', acreage: 200, crop: 'organic wheat', region: 'Oregon' }, blocks: [...] }

fb("Walk-in cooler temperature 4 celsius")
// => { type: 'observe.reading', state: { temperature: { value: 4, unit: 'celsius' } }, blocks: [...] }

fb("Ordered 50kg flour from Stone Mill")
// => { type: 'transfer.order', state: { weight: { value: 50, unit: 'kg' } }, blocks: [...] }

No types to memorize. No schemas to configure. No API calls — fb() is pure pattern matching, runs locally, costs nothing.

Programmatic API

javascript
const fb = require('foodblock')

// Create a farm
const farm = fb.create('actor.producer', { name: 'Green Acres Farm' })
// => { hash: 'e3b0c4...', type: 'actor.producer', state: {...}, refs: {} }

// Create a product with provenance
const wheat = fb.create('substance.ingredient', { name: 'Organic Wheat' }, { source: farm.hash })
const flour = fb.create('substance.product', { name: 'Stoneground Flour' }, { source: wheat.hash })
const bread = fb.create('substance.product', {
  name: 'Sourdough',
  price: 4.50
}, {
  seller: bakery.hash,
  inputs: [flour.hash, water.hash, yeast.hash]
})

// Update (creates new block, old one preserved)
const updated = fb.update(bread.hash, 'substance.product', {
  name: 'Sourdough',
  price: 5.00
}, { seller: bakery.hash })
// updated.refs.updates === bread.hash

// Sign and verify
const keys = fb.generateKeypair()
const signed = fb.sign(bread, farm.hash, keys.privateKey)
// signed.protocol_version === '0.4.0'
const valid = fb.verify(signed, keys.publicKey) // true

// Provenance chain
const history = await fb.chain(updated.hash, resolve)
// [{ price: 5.00 }, { price: 4.50 }] — newest to oldest

// Validate against schema
const errors = fb.validate(bread)  // [] if valid

// Tombstone (GDPR erasure)
const ts = fb.tombstone(bread.hash, user.hash, { reason: 'gdpr_erasure' })

// Offline queue
const queue = fb.offlineQueue()
queue.create('transfer.order', { total: 12.00 }, { seller: farmHash })
await queue.sync('https://api.example.com/foodblock')

// --- Human Interface ---

// Aliases: use @names instead of hashes
const reg = fb.registry()
const myFarm = reg.create('actor.producer', { name: 'Green Acres' }, {}, { alias: 'farm' })
const myWheat = reg.create('substance.ingredient', { name: 'Wheat' }, { source: '@farm' })
// '@farm' resolves to myFarm.hash automatically

// FoodBlock Notation: one-line text format
const blocks = fb.parseAll(`
@farm = actor.producer { "name": "Green Acres Farm" }
@wheat = substance.ingredient { "name": "Wheat" } -> source: @farm
`)

// Explain: human-readable narrative from graph
const story = await fb.explain(bread.hash, resolve)
// "Sourdough ($4.50). By Green Acres Bakery. Made from Organic Flour (Green Acres Farm)."

// URIs: shareable block references
fb.toURI(bread)                          // 'fb:a1b2c3...'
fb.toURI(bread, { alias: 'sourdough' })  // 'fb:substance.product/sourdough'

// --- Templates ---

// Use built-in templates for common patterns
const chain = fb.fromTemplate(fb.TEMPLATES['supply-chain'], {
  farm: { state: { name: 'Green Acres Farm' } },
  crop: { state: { name: 'Organic Wheat' } },
  processing: { state: { name: 'Stone Milling' } },
  product: { state: { name: 'Flour', price: 3.20 } }
})
// Returns 5 blocks in dependency order, with @alias refs auto-resolved

// Create custom templates
const myTemplate = fb.createTemplate('Bakery Review', 'Review a bakery product', [
  { type: 'actor.venue', alias: 'bakery', required: ['name'] },
  { type: 'substance.product', alias: 'item', refs: { seller: '@bakery' } },
  { type: 'observe.review', alias: 'review', refs: { subject: '@item' }, required: ['rating'] }
])

// --- Federation ---

// Discover another FoodBlock server
const info = await fb.discover('https://farm.example.com')
// { protocol: 'foodblock', version: '0.4.0', types: [...], count: 142 }

// Resolve blocks across multiple servers
const resolve = fb.federatedResolver([
  'http://localhost:3111',
  'https://farm.example.com',
  'https://market.example.com'
])
const block = await resolve('a1b2c3...')  // tries each server in order

Sandbox

Try it locally with zero setup:

bash
cd sandbox
node server.js
bash
# List all blocks
curl localhost:3111/blocks

# Filter by type
curl localhost:3111/blocks?type=substance.product

# Get head blocks only (latest versions)
curl localhost:3111/blocks?type=substance.product&heads=true

# Provenance chain
curl localhost:3111/chain/<hash>

# Create a block
curl -X POST localhost:3111/blocks \
  -H "Content-Type: application/json" \
  -d '{"type":"observe.review","state":{"rating":5,"text":"Amazing"},"refs":{"subject":"<product_hash>"}}'

# Batch create (offline sync)
curl -X POST localhost:3111/blocks/batch \
  -H "Content-Type: application/json" \
  -d '{"blocks":[...]}'

# Tombstone (content erasure)
curl -X DELETE localhost:3111/blocks/<hash>

# Federation discovery
curl localhost:3111/.well-known/foodblock

# List templates
curl localhost:3111/blocks?type=observe.template

# Natural language entry point
curl -X POST localhost:3111/fb \
  -H "Content-Type: application/json" \
  -d '{"text":"Sourdough bread, $4.50, organic, contains gluten"}'

# Forward traversal (what references this block?)
curl localhost:3111/forward/<hash>

# Natural language → blocks
curl -X POST localhost:3111/fb \
  -H "Content-Type: application/json" \
  -d '{"text":"Sourdough bread, $4.50, organic, contains gluten"}'

# List vocabularies
curl localhost:3111/blocks?type=observe.vocabulary

The sandbox ships preloaded with 47 blocks modelling a complete bakery supply chain — from farm to consumer, including certifications, shipments, cold chain readings, reviews, and operational vocabularies.

API

fb(text) → { blocks, primary, type, state, text }

The natural language entry point. Pass any food-related text, get FoodBlocks back. Detects intent (product, review, farm, order, certification, reading, process, venue, ingredient), extracts quantities (price, weight, volume, temperature, rating), flags (organic, gluten-free, kosher, etc.), and relationships ("from X", "at Y", "by Z"). No LLM — pure regex pattern matching against built-in vocabularies.

create(type, state, refs) → block

Create a new FoodBlock. Returns { hash, type, state, refs }.

update(previousHash, type, state, refs) → block

Create an update block that supersedes a previous version. Automatically adds refs.updates.

hash(type, state, refs) → string

Compute the SHA-256 hash without creating a block object.

chain(hash, resolve, opts) → block[]

Follow the update chain backwards. resolve is async (hash) => block | null.

tree(hash, resolve, opts) → { block, ancestors }

Follow ALL refs recursively to build the full provenance tree.

head(hash, resolveForward) → string

Find the latest version in an update chain.

sign(block, authorHash, privateKey) → wrapper

Sign a block with Ed25519. Returns { foodblock, author_hash, signature, protocol_version }.

verify(wrapper, publicKey) → boolean

Verify a signed block wrapper.

generateKeypair() → { publicKey, privateKey }

Generate a new Ed25519 keypair for signing.

encrypt(value, recipientPublicKeys) → envelope

Encrypt a value for multiple recipients using envelope encryption (Section 7.2).

decrypt(envelope, privateKey, publicKey) → value

Decrypt an encryption envelope.

validate(block, schema?) → string[]

Validate a block against its declared schema or a provided schema. Returns an array of error messages (empty = valid).

tombstone(targetHash, requestedBy, opts?) → block

Create a tombstone block for content erasure (Section 5.4).

offlineQueue() → Queue

Create an offline queue for local-first block creation with batch sync.

query(resolve) → Query

Fluent query builder:

javascript
const results = await fb.query(resolver)
  .type('substance.product')
  .byRef('seller', bakeryHash)
  .whereLt('price', 10)
  .latest()
  .limit(20)
  .exec()

registry() → Registry

Alias registry for human-readable references. Use @name in refs instead of hashes.

parse(line) → { alias, type, state, refs }

Parse a single line of FoodBlock Notation (FBN).

parseAll(text) → block[]

Parse multiple lines of FBN.

format(block, opts?) → string

Format a block as FBN text.

explain(hash, resolve) → string

Generate a human-readable narrative from a block's provenance graph.

toURI(block, opts?) → string

Convert a block to a fb: URI. toURI(block)fb:<hash>, toURI(block, { alias: 'name' })fb:<type>/<alias>.

fromURI(uri) → object

Parse a fb: URI into { hash } or { type, alias }.

createTemplate(name, description, steps, opts?) → block

Create a template block (observe.template) that defines a reusable workflow pattern.

fromTemplate(template, values) → block[]

Instantiate a template into real blocks. values maps step aliases to { state, refs } overrides. @alias references between steps are resolved automatically.

TEMPLATES

Built-in templates: supply-chain, review, certification.

discover(serverUrl, opts?) → info

Fetch a server's /.well-known/foodblock discovery document.

federatedResolver(servers, opts?) → resolve

Create a resolver that tries multiple servers in priority order. Returns async (hash) => block | null with optional caching.

createVocabulary(domain, forTypes, fields, opts?) → block

Create a vocabulary block (observe.vocabulary) defining canonical field names, types, and natural language aliases for a domain.

mapFields(text, vocabulary) → { matched, unmatched }

Extract field values from natural language text using a vocabulary's aliases. Returns matched fields and unmatched terms.

VOCABULARIES

Built-in vocabulary definitions: bakery, restaurant, farm, retail, lot, units, workflow.

quantity(value, unit, type?) → { value, unit }

Create a quantity object. Validates unit against the units vocabulary if type is provided (e.g. 'weight', 'volume', 'temperature').

transition(from, to) → boolean

Validate a workflow state transition against the workflow vocabulary's transition map (e.g. draft→order is valid, draft→shipped is not).

nextStatuses(status) → string[]

Get valid next statuses for a given workflow status.

localize(block, locale, fallback?) → block

Extract locale-specific text from multilingual state fields. Fields using { en: "...", fr: "..." } nested objects are resolved to the requested locale.

forward(hash, resolveForward) → { referencing, count }

Find all blocks that reference a given hash. Returns blocks grouped by ref role.

recall(sourceHash, resolveForward, opts?) → { affected, depth, paths }

Trace contamination/recall paths downstream via BFS. Starting from a source block, follows all forward references recursively. Supports types and roles filters.

downstream(ingredientHash, resolveForward) → block[]

Find all downstream substance blocks that use a given ingredient (convenience wrapper around recall).

merkleize(state) → { root, leaves, tree }

Build a Merkle tree from a state object for selective disclosure.

selectiveDisclose(state, fieldNames) → { disclosed, proof, root }

Reveal only specific fields with a Merkle proof that they belong to the block.

verifyProof(disclosed, proof, root) → boolean

Verify a selective disclosure proof.

merge(hashA, hashB, resolve, opts?) → block

Create a merge block resolving a fork between two update chain heads.

attest(targetHash, attestorHash, opts?) → block

Create an attestation block confirming a claim. opts.confidence: verified, probable, unverified.

dispute(targetHash, disputerHash, reason) → block

Create a dispute block challenging a claim.

trustScore(hash, allBlocks) → number

Compute net trust score: attestations minus disputes.

createSnapshot(blocks, opts?) → block

Summarize a set of blocks into a snapshot with a Merkle root for archival verification.

The Axiom

A FoodBlock's identity is its content: SHA-256(canonical(type + state + refs)).

Everything follows from this:

  • Immutability — change content, change identity
  • Determinism — same content, same hash, anywhere
  • Deduplication — identical products resolve to one block
  • Tamper evidence — any modification is detectable
  • Offline validity — no server needed to create blocks
  • Provenance — refs form a directed graph of history

Seven operational rules govern the protocol's use:

  1. A FoodBlock has exactly three fields: type, state, refs.
  2. Authentication: { foodblock, author_hash, signature, protocol_version } using Ed25519.
  3. Encrypted state: _ prefixed keys contain envelope-encrypted values.
  4. Author-scoped updates: only the original author or approved actor may create successors.
  5. Tombstones erase content while preserving graph structure.
  6. Schema declarations are optional.
  7. The protocol is open. No permission required.

Canonical JSON

Deterministic hashing requires deterministic serialization. Aligns with RFC 8785 (JSON Canonicalization Scheme) for number formatting and key ordering:

  • Keys sorted lexicographically at every nesting level
  • No whitespace between tokens
  • Numbers: no trailing zeros, no leading zeros. -0 normalized to 0.
  • Strings: Unicode NFC normalization
  • Arrays in refs: sorted lexicographically (set semantics)
  • Arrays in state: preserve declared order (sequence semantics)
  • Null values: omitted
  • Booleans: true or false

Database Schema

sql
CREATE TABLE foodblocks (
    hash             VARCHAR(64) PRIMARY KEY,
    type             VARCHAR(100) NOT NULL,
    state            JSONB NOT NULL DEFAULT '{}',
    refs             JSONB NOT NULL DEFAULT '{}',
    author_hash      VARCHAR(64),
    signature        TEXT,
    protocol_version VARCHAR(10) DEFAULT '0.3',
    chain_id         VARCHAR(64),
    is_head          BOOLEAN DEFAULT TRUE,
    created_at       TIMESTAMP DEFAULT NOW()
);

Full schema with indexes, author-scoped head trigger, and tombstone trigger: sql/schema.sql

Cross-Language Test Vectors

test/vectors.json contains 30 known inputs and expected hashes — including tombstone blocks, schema references, vocabulary blocks, attestation blocks, merge blocks, RFC 8785 number edge cases, and more. Any SDK in any language must produce identical hashes for these inputs. If JavaScript and Python disagree, the protocol is broken.

Project Structure

code
foodblock/
├── spec/whitepaper.md           Protocol specification (v0.4)
├── sdk/javascript/              JavaScript SDK (reference implementation)
│   ├── src/                     block, chain, verify, encrypt, validate, offline, tombstone,
│   │                            alias, notation, explain, uri, template, federation,
│   │                            vocabulary, forward, merge, merkle, snapshot, attestation
│   └── test/                    Test suite (104 tests)
├── sdk/python/                  Python SDK
│   ├── foodblock/               block, chain, verify, validate, tombstone,
│   │                            alias, notation, explain, uri, template, federation,
│   │                            vocabulary, forward, merge, merkle, snapshot, attestation
│   └── tests/                   Test suite (80 tests)
├── sdk/go/                      Go SDK
│   └── foodblock.go             block, chain, sign/verify, tombstone
├── sdk/swift/                   Swift SDK
│   └── Sources/                 block, tombstone
├── mcp/                         MCP server for AI agent integration (15 tools)
├── sandbox/                     Local sandbox server
│   ├── server.js                Zero-dependency HTTP API + federation discovery
│   └── seed.js                  47-block bakery chain + templates + vocabularies
├── sql/schema.sql               Postgres schema + triggers
├── test/vectors.json            Cross-language test vectors (30 vectors)
└── LICENSE                      MIT

Sector Coverage

The six base types cover all fourteen food industry sectors:

SectorKey Types
Primary Productionactor.producer, place.farm, transform.harvest
Processingactor.maker, transform.process, observe.inspection
Distributionactor.distributor, transfer.shipment, observe.reading
Retailsubstance.product, transfer.order
Hospitalityactor.venue, transfer.booking, observe.review
Food Serviceobserve.plan, transform.process
Waste & Sustainabilityactor.sustainer, substance.surplus, transfer.donation
Regulationactor.authority, observe.certification
Education & Mediaactor.creator, observe.post
Communityactor.group, observe.event
Health & Nutritionactor.professional, observe.assessment
Financetransfer.investment, observe.market
Cultural Foodobserve.certification, place.region
Food Technologyactor.innovator, observe.experiment

License

MIT — use it however you want.

Links

常见问题

io.github.FoodXDevelopment/foodblock-mcp 是什么?

適用於任何 AI agent 的 food data 工具;以英文描述食物,即可回傳結構化資料。

相关 Skills

前端设计

by anthropics

Universal
热门

面向组件、页面、海报和 Web 应用开发,按鲜明视觉方向生成可直接落地的前端代码与高质感 UI,适合做 landing page、Dashboard 或美化现有界面,避开千篇一律的 AI 审美。

想把页面做得既能上线又有设计感,就用前端设计:组件到整站都能产出,难得的是能避开千篇一律的 AI 味。

编码与调试
未扫描165.3k

网页应用测试

by anthropics

Universal
热门

用 Playwright 为本地 Web 应用编写自动化测试,支持启动开发服务器、校验前端交互、排查 UI 异常、抓取截图与浏览器日志,适合调试动态页面和回归验证。

借助 Playwright 一站式验证本地 Web 应用前端功能,调 UI 时还能同步查看日志和截图,定位问题更快。

编码与调试
未扫描165.3k

网页构建器

by anthropics

Universal
热门

面向复杂 claude.ai HTML artifact 开发,快速初始化 React + Tailwind CSS + shadcn/ui 项目并打包为单文件 HTML,适合需要状态管理、路由或多组件交互的页面。

在 claude.ai 里做复杂网页 Artifact 很省心,多组件、状态和路由都能顺手搭起来,React、Tailwind 与 shadcn/ui 组合效率高、成品也更精致。

编码与调试
未扫描165.3k

相关 MCP Server

GitHub

编辑精选

by GitHub

热门

GitHub 是 MCP 官方参考服务器,让 Claude 直接读写你的代码仓库和 Issues。

这个参考服务器解决了开发者想让 AI 安全访问 GitHub 数据的问题,适合需要自动化代码审查或 Issue 管理的团队。但注意它只是参考实现,生产环境得自己加固安全。

编码与调试
89.1k

by Context7

热门

Context7 是实时拉取最新文档和代码示例的智能助手,让你告别过时资料。

它能解决开发者查找文档时信息滞后的问题,特别适合快速上手新库或跟进更新。不过,依赖外部源可能导致偶尔的数据延迟,建议结合官方文档使用。

编码与调试
60.0k

by tldraw

热门

tldraw 是让 AI 助手直接在无限画布上绘图和协作的 MCP 服务器。

这解决了 AI 只能输出文本、无法视觉化协作的痛点——想象让 Claude 帮你画流程图或白板讨论。最适合需要快速原型设计或头脑风暴的开发者。不过,目前它只是个基础连接器,你得自己搭建画布应用才能发挥全部潜力。

编码与调试
49.5k

评论