triggr
v0.1.0
Published
Post-MCP tool manifest runtime for AI agents. Static manifests, direct invocation, 17x fewer tokens.
Downloads
116
Maintainers
Readme
Why triggr?
MCP treats tool access as a systems problem — protocols, transports, server lifecycle. In practice, it's a description problem: tell the AI what's available and how to call it.
triggr replaces MCP servers with static YAML manifests and direct invocation.
| | MCP | triggr | |---|---|---| | Schema overhead (50 tools) | ~15,000 tokens | ~750 tokens | | Simple lookup latency | 2-5s (server boot) | ~200ms (CLI exec) | | Boilerplate per tool | 40+ lines TypeScript | 5-10 lines YAML | | Cold start | 1-5s | 0ms (cli://) | | Failure blast radius | All tools down | Per-tool isolation | | Agent compatibility | MCP-compatible only | Any (CLI + HTTP) |
Install
npm install -g triggrQuick Start
# Create a manifest
triggr init
# Validate it
triggr check
# See the compact tool index
triggr list
# Run a tool
triggr run hello --name WorldManifest Format
Tools are defined in triggr.yaml or *.tools.yaml files:
name: github
version: "1.0"
tools:
- name: list_prs
description: "List open pull requests"
invoke:
type: cli
command: "gh pr list --state {state} --json number,title,url"
parse: json
parameters:
state:
type: string
enum: [open, closed, merged]
default: open
cache:
ttl: 60s
key: [state]
- name: create_issue
description: "Create a new issue"
invoke:
type: http
method: POST
url: "https://api.github.com/repos/{owner}/{repo}/issues"
auth: "${GITHUB_TOKEN}"
parameters:
owner: { type: string, required: true }
repo: { type: string, required: true }
title: { type: string, required: true }
body: { type: string }Three Invocation Backends
cli:// — Fork + exec. No server.
invoke:
type: cli
command: "gh pr list --json number,title"
parse: json
timeout: 10sThe CLI binary is executed directly via execFile (no shell injection). Stdout is parsed as JSON, text, or lines.
http:// — Direct HTTP calls.
invoke:
type: http
method: GET
url: "https://api.example.com/items?limit={limit}"
auth: "${API_TOKEN}"No middleware, no relay. Auth via environment variables.
sidecar:// — Auto-managed processes. (Coming soon)
invoke:
type: sidecar
name: my-server
endpoint: "/search"
idle_timeout: 120sLazy-started on first call, auto-stopped after idle timeout.
Two-Phase Schema Loading
The core token-saving mechanism. Instead of injecting full JSON Schema for every tool:
Phase 1 — Compact index (~15 tokens per tool, always in context):
$ triggr list
github:list_prs — List open pull requests [state?]
github:create_issue — Create a new issue [owner, repo, title, body?]
slack:send — Send a message [channel, text]
db:query — Run read-only SQL [query]Phase 2 — On-demand expansion (only when the AI selects a tool):
$ triggr list --expandedReturns full parameter schemas, enum values, and cache config for individual tools.
Result Projection
Return only the fields you need:
triggr run github:list_prs --project number,title,author.login[
{ "number": 421, "title": "Fix timeout", "author": { "login": "alice" } },
{ "number": 418, "title": "Add streaming", "author": { "login": "bob" } }
]Caching
Declarative per-tool TTL caching. Repeated calls with the same args return instantly:
cache:
ttl: 60s
key: [state] # only these args form the cache key$ triggr run github:list_prs --state open --debug
→ cache: MISS
→ duration: 142ms
$ triggr run github:list_prs --state open --debug
→ cache: HIT
→ duration: 0msCLI Reference
| Command | Description |
|---|---|
| triggr init | Create a starter triggr.yaml |
| triggr check [path] | Validate manifest files |
| triggr list | Show compact tool index |
| triggr list --expanded | Show full tool schemas |
| triggr list --json | Output index as JSON |
| triggr run <tool> [--key value] | Invoke a tool |
| triggr run <tool> --debug | Show cache status, duration, details |
| triggr run <tool> --pretty | Pretty-print JSON output |
| triggr run <tool> --project fields | Project specific fields from result |
Programmatic API
import { loadAllManifests, invokeTool, generateCompactIndex } from "triggr";
const manifests = await loadAllManifests(process.cwd());
// Generate compact index for AI context
const index = generateCompactIndex(manifests);
// Invoke a tool
const result = await invokeTool("github:list_prs", { state: "open" }, manifests, {
project: ["number", "title"],
});Manifest Discovery
triggr searches for manifests in this order:
triggr.yamlin current directory*.tools.yamlin current directory.triggr/*.tools.yamlin current directory~/.triggr/*.tools.yaml(global user-level)
Roadmap
- [x]
cli://backend — fork+exec with structured output parsing - [x]
http://backend — direct HTTP calls with auth - [x] Two-phase schema loading — compact index + on-demand expansion
- [x] TTL caching — per-tool, deterministic cache keys
- [x] Result projection — dot-notation field filtering
- [ ]
sidecar://backend — auto-managed processes with health checks - [ ] MCP compatibility adapter — generate MCP handlers from manifests
- [ ] Pack registry —
triggr install github - [ ] Batch invocation — parallel dispatch of independent tool calls
License
MIT
