Agent harness
Pi Agent
Pi Agent connects to MCP servers on its own over Streamable HTTP and lets you set a static Authorization header, so you point it straight at Korely's remote server, no bridge.
Pi is a coding agent. It connects to MCP servers on its own,
either a program it starts on your machine (stdio) or a server it reaches by URL (Streamable HTTP),
and it lets you set a fixed Authorization header holding your key on a URL server, so you can connect to
Korely's remote MCP endpoint directly. Korely reads each memory and writes the
facts on its own servers, closing an older fact when a newer one
contradicts it, and Pi just calls the tools.
Prerequisites
- A Korely API key (
kor_live_...) without theadminpermission. Make it on the dashboard's API keys page, which ticksmemories:readandmemories:writeand leavesadminoff. A key from agent signup hasadminuntil you connect it to a dashboard login, and with it a tool can manage the account's projects and close the account; connecting takesadminaway, and the key keeps working. The hobby plan is free; Pricing lists its limits. - Pi installed (see Pi's MCP docs).
Connect Korely (recommended, native remote header)
Pi reads user-level servers from ~/.pi/agent/mcp.json and
project servers from .pi/mcp.json. Korely's agent memory is a
remote MCP server at https://api.korely.ai/agent/mcp (Streamable
HTTP), authenticated with your key in a static header, no browser login.
Keep the entry, which carries your key, in ~/.pi/agent/mcp.json;
Pi reads .pi/mcp.json only after you have granted trust to the project:
{ "mcpServers": { "korely": { "url": "https://api.korely.ai/agent/mcp", "headers": { "Authorization": "Bearer ${KORELY_API_KEY}" }, "exposure": "direct" } }} "exposure" sets how the model reaches a server's tools. By default
("codemode") the tools can be called only from codemode scripts
that Pi runs, and the model is not told about them. With
"exposure": "direct" the model sees the six Korely tools and can call them by name. Pi registers each server tool as mcp__<server>__<tool>,
for example mcp__korely__korely_get_context.
Set KORELY_API_KEY=kor_live_... in your environment, Pi
interpolates ${KORELY_API_KEY} in header values. Or let
Pi write the entry for you (see Pi's
CLI reference), then add
"exposure": "direct" to it:
pi mcp add korely --url https://api.korely.ai/agent/mcp --bearer-token-env-var KORELY_API_KEY
Without "exposure": "direct" Pi keeps the default
codemode and does not declare the six tools to the model.
To check the connection, run pi mcp list: it connects to every
enabled server and prints its state, its tools and any errors. Inside a Pi
session, /mcp shows the same, and /reload makes Pi
read a file you changed outside the session.
With the community pi-mcp-adapter
pi-mcp-adapter
(MIT-licensed, authored by nicobailon, not an official Pi / pi.dev
product) is an alternative that replaces Pi's built-in MCP support
once installed (pi install npm:pi-mcp-adapter). The same
"headers" entry works with it. The adapter reads several config
files, including Pi's own ~/.pi/agent/mcp.json and
.pi/mcp.json on Pi 0.99 and later; its
configuration doc
lists them all and says which one wins. The adapter also has a bearerToken field (see its authentication
doc); with Korely the "headers" object alone is enough. Verify the adapter against its
README
before relying on it.
By default the adapter routes all MCP tools through a single proxy tool to save
context. To expose the Korely tools as first-class
tools, use the adapter's directTools config on the server entry:
"directTools": true promotes all six, or list the ones you want, for example
"directTools": ["korely_get_context", "korely_add", "korely_search", "korely_get_facts"].
Fallback, mcp-remote stdio bridge
Only if the native remote path misbehaves, you can route through the community
mcp-remote proxy instead. It runs as a local stdio MCP server and
forwards every call to Korely over HTTP with your header attached, useful
because Pi also accepts command-based (stdio) servers.
Requires Node.js / npx on the machine.
{ "mcpServers": { "korely": { "command": "npx", "args": [ "-y", "mcp-remote", "https://api.korely.ai/agent/mcp", "--header", "Authorization:${KORELY_AUTH}" ], "env": { "KORELY_AUTH": "Bearer ${KORELY_API_KEY}" }, "exposure": "direct" } }}
Pi fills in env values, and mcp-remote reads
KORELY_AUTH from its environment. The header argument has no
space after the colon: the space in Bearer <key> lives in the
variable, because a space in an argument can be mangled when npx
starts the process.
Korely MCP also supports OAuth, so Pi can sign you in instead of using a key. The Pi documentation describes OAuth for remote MCP servers. Korely has not tested OAuth with Pi. See Connect with OAuth.
What Pi Agent can do
The Korely server offers six memory tools:
| Tool | What it does |
|---|---|
korely_get_context | The recall call: returns the current facts plus the most relevant memories as one block of text, ready to put in a prompt (the context block). It does not call a language model. |
korely_add | Store a memory. Korely writes facts from it on its servers, each as (subject, predicate, object), and closes an earlier fact, with its end date, when a model decides a new one replaces it. |
korely_search | Search by meaning over the stored memories, best match first. |
korely_get_facts | The facts known about an end user, with point-in-time queries: as_of (what was true then) and known_as_of (what the store knew then). |
korely_correct_fact | Fix or end one fact by its id. Give a new subject, predicate or object and the old fact is closed and a corrected one is written, both kept in history. With close=true the fact is only closed, which is how you forget a fact. Needs a key with the memories:write permission. |
korely_forget_memory | Forget one memory by its id. It drops out of every read and the facts only it stated are closed; with erase=true it is removed for good. Needs memories:write. |
Use it
Korely MCP sends its client short instructions: call korely_get_context before answering, and korely_add once a decision or preference is settled. If Pi Agent follows them, a session looks like this (an example, not a recording):
You › Remember that this repo deploys to Hetzner, not Render. → korely_add("This repo deploys to Hetzner, not Render")
# next session, days laterYou › How do we deploy this? → korely_get_context("deploy") → "This repo deploys to Hetzner..."Pi › This repo deploys to Hetzner (you told me earlier), not Render. ...Scoping
The four tools korely_get_context, korely_add,
korely_search and korely_get_facts accept an
optional user_id so one key can serve many
end users: a read that names
"user-b" never returns a memory written for
"user-a". On a write, pass a user_id or an agent_id. With neither, the remote server stores the memory in the project's shared memory, with no end user, under the name your client gave when it connected (a key confined to one end user writes to that one); details. Omit it on a read and the
read covers every end user the key can see. korely_add and the
three read tools also accept an optional
agent_id.
korely_correct_fact and korely_forget_memory take
the id of a fact or a memory instead, and treat an id from another project
(or, for a confined key, from another end user) as not found. The
Korely MCP page lists every argument.
Why this is more than a notepad. Korely keeps each memory's
text as written and also extracts typed facts with
bi-temporal validity from it. When something changes ("this repo now deploys to Hetzner, not Render"), Korely closes the old fact with its end date instead of overwriting it, so korely_get_context returns
what's true now, and as_of can still replay what was
true before. The Cloud runs on servers in Helsinki; Data and governance says where text is processed.
Related
- Korely MCP, the full MCP surface and other clients.
- Get context, the call behind
korely_get_context. - Memory as a tool, the same pattern when you build the agent loop yourself.