Install
$ agentstack add mcp-mrzdevcore-haira Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ 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.
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
High-level Agentic Instruction & Runtime Architecture The programming language for AI agents and workflows.
Website · Documentation · Examples · ARP Protocol · Generative UI
> Note: Haira is under heavy development and not yet production-ready. APIs and syntax may change. Use at your own risk.
Haira is a compiled language designed from the ground up for building agentic applications. Providers, tools, agents, and workflows are part of the language itself — not frameworks bolted on top. Write your agent logic, compile it to a native binary, and ship it.
import "io"
import "http"
provider openai {
api_key: env("OPENAI_API_KEY")
model: "gpt-4o"
}
tool get_weather(city: string) -> string {
"""Get the current weather for a given city"""
resp, err = http.get("https://wttr.in/${city}?format=j1")
if err != nil { return "Failed to fetch weather data." }
data = resp.json()
current = data["current_condition"][0]
return "${city}: ${current["temp_C"]}C"
}
agent Assistant {
model: openai
system: "You are a helpful assistant. Be concise."
tools: [get_weather]
memory: conversation(max_turns: 10)
temperature: 0.7
}
@post("/api/chat")
workflow Chat(message: string, session_id: string) -> { reply: string } {
reply, err = Assistant.ask(message, session: session_id)
if err != nil { return { reply: "Something went wrong." } }
return { reply: reply }
}
fn main() {
server = http.Server([Chat])
io.println("Server running on :8080")
io.println("UI: http://localhost:8080/_ui/")
server.listen(8080)
}
Architecture
┌─────────────────────────────────────┐
│ .haira source │
└──────────────┬──────────────────────┘
│
┌────────────────────────────────────────────────┐
│ COMPILER │
│ │
│ ┌───────┐ ┌────────┐ ┌──────────┐ │
│ │ Lexer │──▶│ Parser │──▶│ Checker │ │
│ └───────┘ └────────┘ └─────┬────┘ │
│ │ │
│ ┌─────▼──────┐ │
│ │ Codegen │ │
│ │ (Go emit) │ │
│ └─────┬──────┘ │
└──────────────────────────────────┼─────────────┘
│
go build
│
▼
┌─────────────────────────────────────────────────┐
│ NATIVE BINARY │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Haira Runtime │ │
│ │ │ │
│ │ ┌──────────┐ ┌───────┐ ┌──────────┐ │ │
│ │ │ Provider │ │ Agent │ │ Workflow │ │ │
│ │ └──────────┘ └───┬───┘ └────┬─────┘ │ │
│ │ │ │ │ │
│ │ ┌──────────┴───────────┘ │ │
│ │ │ │ │
│ │ ┌──────▼──────┐ ┌──────────────┐ │ │
│ │ │ HTTP Server │ │ MCP Server │ │ │
│ │ │ REST + SSE │ │ stdio / HTTP │ │ │
│ │ └──────┬──────┘ └──────────────┘ │ │
│ │ │ │ │
│ │ ┌──────▼──────┐ ┌──────────────┐ │ │
│ │ │ ARP Bridge │ │ Observe / │ │ │
│ │ │ (protocol) │ │ Langfuse │ │ │
│ │ └──┬──────┬───┘ └──────────────┘ │ │
│ │ │ │ │ │
│ └─────┼──────┼────────────────────────────┘ │
│ │ │ │
│ ┌────▼──┐ ┌─▼────────┐ ┌───────────────┐ │
│ │ SSE │ │WebSocket │ │ SQLite Store │ │
│ │(http) │ │(_arp/v1) │ │ (sessions) │ │
│ └───┬───┘ └────┬─────┘ └───────────────┘ │
└───────┼──────────┼──────────────────────────────┘
│ │
▼ ▼
┌──────────────────────────────────┐
│ UI SDK (Lit) │
│ │
│ ┌──────┐ ┌──────┐ ┌──────────┐ │
│ │ Chat │ │ Form │ │Generative│ │
│ │ UI │ │ UI │ │UI Comps │ │
│ └──────┘ └──────┘ └──────────┘ │
│ │
│ tables, charts, status cards, │
│ code blocks, diffs, key-value, │
│ confirm, choices, forms, │
│ product cards, progress views │
└──────────────────────────────────┘
Data flow: .haira source is compiled through Lexer → Parser → Checker → Go Codegen, then go build produces a single native binary. At runtime, the binary embeds the full Haira runtime (agents, providers, tools, workflows, HTTP server, ARP protocol bridge, UI SDK) — zero external dependencies.
Why Haira?
| What you replace | With Haira | |------------------|------------| | Python + LangChain/LangGraph | agent + tool keywords | | n8n / Make / Zapier | workflow with @post, @get triggers + auto UI | | CrewAI / AutoGen | Multi-agent with handoffs and spawn | | Custom chatbot backend | Agent memory + -> stream + built-in chat UI | | YAML/JSON config files | provider keyword — config in code | | MCP glue code | mcp.Server() / provider { transport: "mcp" } | | Vercel AI SDK + React UI | Generative UI with ui.* components |
Key Features
- 4 agentic keywords —
provider,tool,agent,workflow - Compiles to native binaries — via Go codegen, single executable output
- Generative UI — agents render rich UI components (tables, charts, status cards, forms) via
ui.*helpers - ARP (Agentic Rendering Protocol) — transport-agnostic protocol for agent-to-renderer communication (WebSocket + SSE)
- Auto UI — every workflow gets a form UI at
/_ui/, streaming workflows get a ChatGPT-style chat UI - RESTful triggers —
@get,@post,@put,@deletedecorators - Streaming —
-> streamworkflows served as SSE with WebSocket upgrade - Agent handoffs — agents delegate to other agents with
strategy: "parallel"or"sequential" - Agent memory —
conversation(max_turns: N)per session - Eval framework —
evalblocks for automated agent testing with pass/fail thresholds - Tool lifecycle hooks —
@beforeand@afterblocks for pre/post-processing - Verification loops —
verify { assert ... }inside@retrysteps for assertion-driven retries - Cross-harness export —
--target claude-codegenerates Claude Code agent configs + MCP binary - Pre-built agent templates —
import "agents"for CodeReviewer, Planner, Summarizer, and more - File uploads —
filetype with multipart handling, auto file picker in UI - Workflow steps — named steps with telemetry,
@retry, lifecycle hooks (onerror,onsuccess) - Parallel execution —
spawn { }blocks for concurrent agent calls - Pipe operator —
data |> transform |> output - MCP support — consume external tools (
provider { transport: "mcp" }) and expose workflows as MCP tools (mcp.Server()) - Observability — built-in
observemodule with Langfuse integration - 14 stdlib packages — postgres, sqlite, excel, vector, slack, github, gitlab, langfuse, agents, auth, websearch, healthcheck, and more
- Go-style simplicity — familiar syntax, explicit error handling
The Four Primitives
Provider — LLM backend configuration
provider openai {
api_key: env("OPENAI_API_KEY")
model: "gpt-4o"
}
// Azure OpenAI
provider azure {
api_key: env("AZURE_OPENAI_API_KEY")
endpoint: env("AZURE_OPENAI_ENDPOINT")
model: env("AZURE_OPENAI_DEPLOYMENT_NAME")
api_version: "2025-01-01-preview"
}
// Local models via Ollama
provider local {
endpoint: "http://localhost:11434/v1"
model: "llama3"
}
Any OpenAI-compatible API works — set endpoint and model.
Tool — function with LLM-visible description
tool search_kb(query: string) -> string {
"""Search the knowledge base for relevant articles"""
resp, err = http.get("https://api.example.com/search?q=${query}")
if err != nil { return "Search failed." }
return resp.body
}
Agent — LLM entity with model, prompt, and tools
agent SupportBot {
model: openai
system: "You are a helpful customer support agent."
tools: [search_kb]
memory: conversation(max_turns: 20)
temperature: 0.3
}
Three ways to call an agent:
reply, err = SupportBot.ask("How do I reset my password?")
result, err = SupportBot.run("Help with billing")
return SupportBot.stream(message, session: session_id)
Workflow — function with a trigger
@post("/api/support")
workflow Support(message: string, session_id: string) -> { reply: string } {
reply, err = SupportBot.ask(message, session: session_id)
if err != nil { return { reply: "Something went wrong." } }
return { reply: reply }
}
Generative UI
Agents can render rich UI components directly into the chat. Tools return ui.* helpers that display tables, charts, status cards, and more — no frontend code required:
tool query_data(sql: string) -> string {
"""Execute a SQL query and display results as a table"""
rows, err = db.query(sql)
if err != nil {
return ui.status_card("error", "Query Failed", conv.to_string(err))
}
headers = keys(rows[0])
table_rows = []
for row in rows {
cells = []
for h in headers {
cells = array.push(cells, conv.to_string(row[h]))
}
table_rows = array.push(table_rows, cells)
}
return ui.table("Results", headers, table_rows)
}
tool visualize(chart_type: string, title: string, labels: string, datasets: string) -> string {
"""Create a chart visualization"""
return ui.chart(chart_type, title, json.parse(labels), json.parse(datasets))
}
Available UI components:
| Component | Helper | Description | |-----------|--------|-------------| | Status Card | ui.status_card(status, title, message?) | Success/error/warning/info indicator | | Table | ui.table(title, headers, rows) | Searchable data table | | Chart | ui.chart(type, title, labels, datasets) | Line, bar, pie, scatter, area charts | | Key-Value | ui.key_value(title, items) | Labeled property list | | Code Block | ui.code_block(title, language, code) | Syntax-highlighted code | | Diff | ui.diff(title, before, after) | Before/after comparison | | Progress | ui.progress(title, steps) | Multi-step progress tracker | | Form | ui.form(title, fields) | Interactive form input | | Confirm | ui.confirm(title, message?) | Yes/no confirmation dialog | | Choices | ui.choices(title, options) | Option picker (buttons/list) | | Product Cards | ui.product_cards(title, cards) | Product card grid with images | | Group | ui.group(child1, child2, ...) | Compose multiple components |
Agent Handoffs
Agents can delegate to specialized agents automatically:
agent FrontDesk {
model: openai
system: "Greet users. Hand off billing questions to BillingAgent."
handoffs: [BillingAgent, TechAgent]
memory: conversation(max_turns: 10)
}
agent BillingAgent {
model: openai
system: "You handle billing and payment questions."
}
agent TechAgent {
model: openai
system: "You handle technical support questions."
}
Streaming
@post("/api/stream")
workflow Stream(message: string, session_id: string) -> stream {
return Assistant.stream(message, session: session_id)
}
Streaming workflows support two transports:
- SSE — clients requesting
Accept: text/event-streamget SSE chunks - WebSocket — clients connect to
/_arp/v1for bidirectional ARP communication
Both transports deliver the same data. The built-in chat UI automatically upgrades to WebSocket when available, falling back to SSE.
Workflow Steps & Lifecycle Hooks
@webui(title: "File Summarizer", description: "Upload a text file and get an AI summary")
@post("/api/summarize")
workflow Summarize(document: file, context: string) -> { summary: string } {
onerror err {
io.eprintln("Workflow failed: ${err}")
return { summary: "Error: ${err}" }
}
step "Read file" {
content, read_err = io.read_file(document)
if read_err != nil { return { summary: "Failed to read file." } }
}
step "Summarize" {
reply, err = Summarizer.ask(content)
if err != nil { return { summary: "AI error." } }
}
return { summary: reply }
}
Steps provide named telemetry. @retry adds automatic retry with backoff:
@retry(max: 10, delay: 5000, backoff: "exponential")
step "Call external API" {
result = http.get(url)
}
Auto UI
Every workflow automatically gets a web UI — zero configuration:
/_ui/— index page listing all workflows/_ui/— form UI for regular workflows, chat UI for streaming workflows@webui(title: "...", description: "...")— optional UI customizationfileparams — automatically render as file pickers with multipart uploadHAIRA_DISABLE_UI=true— disable all auto-UIs for production
Multi-Agent with Parallel Execution
@post("/api/analyze")
workflow Analyze(topic: string) -> { results: [string] } {
results = spawn {
Researcher.ask("Find facts about ${topic}")
Critic.ask("Find counterarguments about ${topic}")
Summarizer.ask("Write a summary about ${topic}")
}
return { results: results }
}
MCP (Model Context Protocol)
Haira has built-in MCP support in both directions — consume external tools and expose workflows as tools.
MCP Client — Use External Tools
Connect to any MCP server. The agent discovers and uses its tools automatically:
import "http"
provider filesystem {
transport: "mcp"
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
agent Assistant {
model: openai
system: "You are a helpful assistant with file system access."
mcp: [filesystem]
}
SSE transport works too — connect to remote MCP servers over HTTP:
provider remote_tools {
transport: "mcp"
endpoint: "http://tools-server:9000/sse"
}
MCP Server — Expose Workflows as Tools
Any workflow can be exposed as an MCP tool for external agents (Claude Code, Cursor, other Haira agents):
import "mcp"
workflow Summarize(text: string) -> { summary: string } {
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [mrzdevcore](https://github.com/mrzdevcore)
- **Source:** [mrzdevcore/haira](https://github.com/mrzdevcore/haira)
- **License:** Apache-2.0
- **Homepage:** https://haira.dev/
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.