The context layer for your GitHub org
One API turns your whole GitHub organization into structured, LLM-ready context — ownership, dependency graph, contributor expertise, PR & review context, semantic retrieval, and activity. Call it directly, or connect the official MCP server and any agent gets it as native tools.
Overview
Every endpoint is scoped to your organization, derived from your API key and GitHub App install — you never pass an org id. Read endpoints return pre-computed, relationship-aware context; webhooks push updates to you in real time.
| Value | |
|---|---|
| Base URL | https://eos.dev/api/v1 |
| Auth | Bearer API key (eos_…) |
| Format | JSON · { data, meta } |
| Versioning | X-EOS-API-Version: 1 (additive only) |
Quickstart
Three steps from zero to your first context call:
1. Install the EOS GitHub App on the repos you want context for — every surface is scoped to what the App can see. 2. Create an API key in Settings → API (pick the scopes you need). 3. Call the API:
curl "https://eos.dev/api/v1/context/ownership?repo=acme/app&path=services/auth" \
-H "Authorization: Bearer eos_your_key_here"Or with the TypeScript SDK:
import { EosClient } from "@eos-ai/sdk";
const eos = new EosClient({ apiKey: process.env.EOS_API_KEY });
const { data } = await eos.context.ownership({ repo: "acme/app", path: "services/auth" });
console.log(data.owners[0].login, data.owners[0].share); // "alex.kim" 0.84Authentication & scopes
Pass your key as a Bearer token on every request. Any org member can create a key from Settings → API in the console; manage, rotate and revoke them there. A key is scoped to the organization it was minted for and only grants the scopes you select — pick the least it needs.
Keys & the GitHub App. Context is only available for repositories the EOS GitHub App can see. A key inherits that install’s scope — it can read context for those repos and nothing else. Install or adjust repository access from the console at any time.
Authorization: Bearer eos_xxxxxxxxxxxxxxxxxxxxxxxx| Scope | Grants |
|---|---|
| read:context | All context surfaces: ownership & expertise, architecture & dependency graph, contributors, PR & review context, and activity/hotspots. |
| read:search | Semantic retrieval over the org (POST /context/search) — LLM-ready chunks with citations. |
The console authenticates by session cookie instead of a key; both resolve to the same org-scoped access.
Limits & usage
The unit is one context request (one API call or one MCP tool call). Every plan gets the full API surface — tiers gate volume, not endpoints. Two limits apply in parallel: a short-window rate limit (hour + day) that protects the service, and a monthly quota. Every response carries both, so a client (or an agent) can pace itself:
X-RateLimit-Limit: 100 # daily request cap for your plan
X-RateLimit-Remaining: 98
X-RateLimit-Reset: 34200 # seconds until the daily window resets (midnight UTC)
X-EOS-Quota-Limit: 5000 # monthly context-request quota
X-EOS-Quota-Used: 1287
X-EOS-Quota-Remaining: 3713
X-EOS-Quota-Warning: 80 # only present at 80% / 100% of the monthly quotaRequests allowed per plan:
| Plan | Per hour | Per day | Per month |
|---|---|---|---|
| Free | 60 | 100 | 5,000 |
| Starter | 200 | 1,000 | Unlimited |
| Pro | 2,000 | 10,000 | Unlimited |
| Enterprise | Unlimited | Unlimited | Unlimited |
The Free tier includes the full API surface and the MCP server. Semantic retrieval and synthesis are powered internally by Claude — folded into pricing, never a separate credit SKU. Exceeding a limit returns 429 with a Retry-After header; the daily limit resets at midnight UTC and the hourly at the top of the hour.
Responses & errors
Successful responses use a { data, meta } envelope. meta carries context like your plan, freshness, and result counts.
{
"data": { "path": "services/auth", "owners": [ … ], ... },
"meta": { "plan": "pro", "freshness": "live" }
}Errors return { error, code }. Branch on code (stable), not the message:
| code | Meaning |
|---|---|
| invalid_request | A query/body parameter failed validation (HTTP 400). |
| unauthorized | Missing or invalid API key (HTTP 401). |
| forbidden_scope | The key lacks the scope the endpoint requires (HTTP 403). |
| rate_limited | Rate limit or monthly quota exceeded — see Retry-After (HTTP 429). |
| not_found | The requested resource doesn't exist (HTTP 404). |
| internal | Unexpected server error (HTTP 500). |
Ownership & expertise
Who owns or knows any file, module, or system — computed from real contribution history, not CODEOWNERS. The answer to “who should review this?” and “who knows auth?”
GET /api/v1/context/ownership?repo=acme/app&path=services/auth
{
"data": {
"path": "services/auth",
"owners": [
{ "login": "alex.kim", "role": "primary", "share": 0.84,
"signals": { "commits_90d": 312, "reviews_90d": 47 } },
{ "login": "ren.park", "role": "backup", "share": 0.11 }
],
"summary": "alex.kim owns services/auth; ren.park is the backup owner.",
"citations": [{ "type": "blame", "path": "services/auth" }]
},
"meta": { "plan": "pro", "freshness": "live" }
}Architecture & dependency graph
A structural map of the org — repos, modules, inter-file dependencies, and coupling (files that change together). The same graph your agents retrieve and the console visualizes.
GET /api/v1/context/graph?module=lib/db
{
"data": {
"root": "lib/db",
"dependents": ["services/auth", "api/gateway", "lib/queue"],
"coupling": [
{ "a": "lib/db", "b": "services/auth", "cochange": 0.61 }
]
},
"meta": { "plan": "pro" }
}Contributor context
Per-person expertise areas, activity footprint, and review history — so an agent can route work to the right human.
GET /api/v1/context/contributors/alex.kim
{
"data": {
"login": "alex.kim",
"expertise": [
{ "area": "services/auth", "score": 0.84 },
{ "area": "lib/db", "score": 0.37 }
],
"reviews_90d": 47, "active_repos": ["acme/api"]
}
}PR & review context
The review graph: who reviews what, turnaround, and related past PRs — plus scored reviewer suggestions with citations.
GET /api/v1/context/pulls/482/reviewers?repo=acme/api
{
"data": {
"pr": { "repo": "acme/api", "number": 482 },
"suggested_reviewers": [
{ "login": "sam.lee", "score": 0.82,
"reason": "closest expertise to changed paths, no open PRs" }
],
"citations": [
{ "type": "pr", "repo": "acme/api", "number": 470 }
]
}
}Semantic retrieval
Natural-language retrieval over the whole org. Returns LLM-ready context chunks with citations to files, PRs, and owners — retrieval that models the organization, not just text.
POST /api/v1/context/search
{ "query": "how does auth refresh work", "limit": 5 }
{
"data": {
"chunks": [
{ "content": "Refresh-token rotation in session.ts …",
"score": 0.91,
"citations": [
{ "type": "file", "path": "services/auth/session.ts" },
{ "type": "pr", "repo": "acme/api", "number": 482 }
] }
]
}
}Activity & hotspots
Where change is concentrated right now — hotspots, churn, and what's moving across the org.
GET /api/v1/context/activity?window=7d
{
"data": {
"hotspots": [
{ "path": "services/auth", "changes_7d": 23, "authors": 4 },
{ "path": "api/gateway", "changes_7d": 17, "authors": 3 }
]
}
}Webhooks
Subscribe an https endpoint and EOS pushes events as they happen — so your agents always call fresh context without polling. Manage subscriptions in Settings → API (Pro+). The signing secret is shown once.
| Event | Fires when |
|---|---|
| context.updated | Any context surface for a path was recomputed after a change. |
| ownership.changed | The owner or backup owner of a file or module changed. |
| graph.changed | Dependencies or coupling for a module changed. |
| contributor.updated | A contributor's expertise or activity footprint shifted. |
| pull.reviewed / pull.merged | A pull request was reviewed or merged. |
| reindex.completed | A repository finished (re)indexing — its context is now fresh. |
Each delivery is a signed POST. Verify X-EOS-Signature (HMAC-SHA256 of the raw body) before trusting it:
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(header), b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}Payloads carry a stable id (the idempotency key), api_version, and are retried up to 3× with backoff.
SDK
The TypeScript SDK wraps every context surface with types. Install @eos-ai/sdk:
import { EosClient } from "@eos-ai/sdk";
const eos = new EosClient({ apiKey: process.env.EOS_API_KEY });
await eos.context.ownership({ repo: "acme/api", path: "services/auth" });
await eos.context.graph({ repo: "acme/api" });
await eos.context.contributor("alex.kim");
await eos.context.reviewers(482, { repo: "acme/api" });
await eos.context.search({ query: "how does auth refresh work" });MCP — for AI agents
Run the official EOS MCP server so any MCP-compatible agent (Claude Desktop, Cursor, Windsurf) gets your org as native tools — zero glue code. It exposes get_ownership, get_graph, get_contributors, suggest_reviewers, search_context and more.
{
"mcpServers": {
"eos": {
"command": "npx",
"args": ["-y", "@eos-ai/mcp-server"],
"env": { "EOS_API_KEY": "eos_your_key_here" }
}
}
}Looking for the raw machine-readable spec? The full OpenAPI document is at /api/docs.