One index. Reach it over MCP or plain HTTP.
Every route returns typed, cited structure a model consumes directly. The MCP server is the front door most agents use; the same behaviour is one POST away for any runtime.
All routes are served from the API host. Responses are JSON. Requests with a body are application/json.
https://api.ipnops.aiMCP server
A Streamable-HTTP, stateless MCP server at POST /mcp. Add one connector and six tools appear inside your runtime: ipnops_search, ipnops_answer, ipnops_extract, ipnops_research, ipnops_research_status, and ipnops_monitor. Each ships an outputSchema, so tool results arrive as typed structure — not text to re-parse.
# one connector — Ipnops becomes an agent tool
{ "ipnops": {
"transport": "http",
"url": "https://api.ipnops.ai/mcp"
} }{ "tools": [
{ "name": "ipnops_search", "outputSchema": {…} },
{ "name": "ipnops_answer", "outputSchema": {…} },
…extract, research, research_status, monitor
] }A tools/call to answer returns the same AnswerResult shape documented under /answer as structuredContent.
POST /search
Hybrid retrieve over the live-web index: a lexical arm and a dense semantic arm, fused and reranked. Returns typed highlights, each self-citing its source passage.
curl -sS https://api.ipnops.ai/search \
-H "content-type: application/json" \
-d '{ "query": "sqlite file format" }'{ "highlights": [{
"text": "…passage…", "score": 0.91,
"source": { "url": "…" } }],
"arms": { "lexical": true, "dense": true, "reranked": true } }POST /answer
Consolidates highlights into one grounded answer with Ipnops' own tiered reasoner. The response is the agent-native shape: marker-per-claim citations, a claims array with per-claim verdicts and evidence quotes, one calibrated confidence scalar, and a sufficiency verdict that says whether the evidence actually covered the question.
curl -sS https://api.ipnops.ai/answer \
-H "content-type: application/json" \
-d '{ "query": "who maintains sqlite?" }'{ "answer": "… [1] … [2]",
"citations": [{ "marker": 1, "url": "…", "text": "…" }],
"claims": [{ "text": "…", "verdict": "supported",
"quotes": ["…"], "grounded": true }],
"confidence": 0.84, "sufficiency": "supported",
"conflicts": [], "grounding": "own-index", "tier": "floor" }grounding is one of own-index, web, places, or none — the reach ladder falls through in that order and never fabricates when it misses. sufficiency is supported, conflicting (sources disagree — see conflicts), or insufficient (treat the answer as an abstain).
POST /research
Deep research as a durable run. Returns a run_id immediately (202); the engine then iterates — answer, find the claims it couldn't ground, crawl the gap, re-answer — checkpointing every step. The run survives restarts, and pages crawled along the way stay in the index.
curl -sS https://api.ipnops.ai/research \
-H "content-type: application/json" \
-d '{ "query": "…" }'
# 202 ◂
{ "run_id": "run_5c1f…", "status": "queued" }# poll
GET /research/:id
# stream — SSE, resumes from Last-Event-ID
GET /research/:id/events
# events: started → iteration → gap → crawl → completed
# cooperative cancel
POST /research/:id/cancelThe terminal result is the same AnswerResult shape as /answer, plus iterations and pagesIndexed.
POST /monitor
Watch a question instead of asking it once. Each sweep re-answers the query and diffs the grounded claim set against the last snapshot — a deterministic normalized-text comparison, zero extra model calls. The webhook fires only when the facts change: rephrasing is silence, a new number is a signal.
POST /monitor # register → 201 { monitor_id }
GET /monitor # list
GET /monitor/:id # one monitor + last snapshot
DELETE /monitor/:id
POST /monitor/run # the cron target — sweep + diff{ "monitor_id": "mon_9b2e…",
"diff": { "addedClaims": ["…"], "removedClaims": ["…"],
"confidenceDelta": -0.05 },
"answer": "… [1]", "citations": […], "confidence": 0.81
}POST /index/seed
Grow the index. Pass exactly one of seed (crawl one domain) or query (fan a free-text query across the discovery ladder and crawl what it finds).
curl -sS https://api.ipnops.ai/index/seed \
-H "content-type: application/json" \
-d '{ "query": "sqlite documentation", "maxSeeds": 5 }'Health & admin
Liveness probe. Returns { status: 'ok' }.
Readiness — reports sidecar + reasoner liveness.
Apply schema.sql (idempotent).
Drop the whole index.