defineEndpoint declares an MCP endpoint: a list of tools and
how its sessions start. You declare it once; Bijection serves it at
/mcp/<name> and handles its grants, limits and tokens. The AI agent itself
(the model, the conversation, voice) runs in your own host.
Three things take part:
- An endpoint is code. It names its tools and how a session starts: the resource type one session acts for and the role a session holds.
- A credential is a key that can only start sessions. It reads no data.
- A session is one conversation. It holds the endpoint’s role on one object, such as one customer, until it expires.
defineMcpServer instead when your app writes its own access rules:
sessions need an access model.
Declaring an endpoint
Give a session a role, and give its credentials a role whose only business permission is the power to grant that role:bijection/access.ts
see covers a customer’s identifier alone, so a credential can tell that a
customer exists and reads none of its fields. The session’s role has no
read.risk, so the fields behind it never reach the agent. maxDuration is
the longest a session can last.
The operation resource is how your access model decides
who may use an operation,
for your staff and for sessions alike. A session holds operation:invoker on
each operation its tools request and operation:reader on each it may only
follow, until it ends. A credential holds operation:agentIssuer on those
operations, which is what lets it give its sessions those roles. An endpoint
with no operation tools needs none of the three.
Then declare the endpoint and export the module:
bijection/mcp.ts
module:export path, the definition itself
and the description the model reads. A tool must be a public query or
operation with explicit validators: publishing it adds
a description, never a way in.
Keep the default export in bijection/mcp.ts. To export it from another
file, pass that file’s path as module to endpointsModule.
Add the tables to your schema, and mount the routes:
bijection/schema.ts
bijection/http.ts
Binding a tool to the session’s object
A tool’s function takes the object it is about as an ordinary argument, so your app and your staff call it too. For a session,bind names that argument:
the model never sees it and cannot supply it, and the session fills it in.
An operation that declares the object as its target needs no bind: its
tool binds the target on its own.
bijection/mcp.ts
bijection/desk.ts
order_details with order_number alone. A bound
argument is a required top-level ID or string. A tool with no arguments can
read the session instead, with endpointSession(ctx) from bijection/mcp.
Three rules shape a tool’s function:
- Select only what the role may read. Reading a whole document asks for every field. A tool that reads a field the session’s role lacks fails as a whole request, not as a tool error.
- Keep an operation’s object type to what the session reads. An operation
reads its target through the view or table it is declared
onbefore it runs. Declare a view that selects only fields the session’s role may read; a view over the whole table is refused for a role that lacks one field. - Write under what you read. A function may write into the table it read, the tables below it in your access model, and grants. An operation that reads an order and writes a refund works when a refund belongs to its order; it is refused when both only belong to the customer.
- Answer refusals as data. Return
{ outcome: "refused", reason }from an operation for the model to read. An error thrown after the function read protected data reaches the caller as a fixed refusal with no reason.
{ kind: "accepted", invocation_id, result }, where result is what your
operation returned.
Tenants and staff directories
Sessions work with any access model, including one whose staff are a workspace directory and one that restricts objects to a tenant. A session principal is never a person of the directory: it holds only what its own grants give it. When the object a session acts for is restricted to a tenant, the session must also pass that tenant. Name the role that carries the pass inancestorRoles: it is granted with the session, on the object’s own tenant,
and ends with it.
bijection/mcp.ts
bijection/access.ts
customer:see above covers a customer’s store).
Deployment validates the coordination tables, required indexes, public tool
definitions, operation authorization and mounted routes before publishing the
program. An incomplete installation names the missing declaration.
Seeing what a session may do
describe reads the declaration. inspect reads an existing session, its
termination history and the current state of each recorded tool contract.
Neither creates a session or needs its signing key; both use deployment
administration. Every command prints its report as JSON with --json.
check validates session admission, the tool contract and the arguments
without executing the tool or consuming its rate allowance. A definite refusal
returns denied and exit status 1. Otherwise it returns requires_execution:
operation permission, data access, business conditions, request ownership and
rate admission are decided for the session when the tool runs. Deployment
administration reads none of your access model’s grants, so a check never
predicts those decisions. A check is an observation, not a reservation or a
promise that a later call succeeds.
bijection mcp try support --key support.voice-prod.agentkey --for <customer id>
starts a one-minute session and lists its tools. Naming a tool and arguments
executes it through the ordinary endpoint, then ends the session.
Creating a credential
support.voice-prod.agentkey.
Bijection keeps no copy. Store the file’s one line as a secret in your
backend, then delete the file.
A credential belongs to one deployment. Create one for each of development,
staging and production.
Use --on <key> when the credential’s role is granted on one object, such as
one organization, rather than on the whole deployment.
To revoke a credential:
Starting a session
In your backend, after you have verified who is calling, start a session and hand the agent’s host its endpoint and token:evidence and does not check it: only a credential
holder can start a session, and you decide when a caller is verified.
A session never changes whom it acts for. Before you know who is calling,
start a session with actsFor: null: it holds no grant and only the tools in
beforeVerification. Once the caller is verified, start another session.
bijection/mcp/node runs in your own Node.js process. Don’t import it from
your bijection/ folder.
Call session.end() when the conversation ends: its grants are deleted and
its token is refused from then on. Otherwise the session ends when it expires.
What a session can and cannot do
- It may call the tools it was offered when it started. A tool you add later reaches new sessions only.
- It may read and change what its role permits on its one object, through its tools.
- Its token calls nothing but its endpoint. A direct call to one of your app’s functions is refused before the function runs, even a function behind one of its tools: the tool list, the bound arguments, the limits and the call log always apply.
- It is never a person: it cannot approve, grant permissions, delegate, or take any decision that names who decided.
- Its requests are limited each minute by
limits.
tool_changed for that session.
When a tool call reads something the session may not, such as a field its
role lacks, the request fails as a whole rather than returning a tool error.
A host that was given only the endpoint and a token can call operation tools:
within one session, the same operation with the same arguments is one
request, so a repeated call never runs twice. A host that needs two identical
requests uses session.connect({ store }), which gives each call its own
identity.
Watching and revoking sessions
bijection mcp calls lists the tool calls sessions made and whether each
completed, from your deployment’s audit log. It shows which session called
which tool for which object, never the arguments. A call that did not complete
was refused by your rules, failed, or was outside the session’s tools or
limits.
The console’s MCP endpoints page shows the same: each declared endpoint, the
installed credentials and recent sessions, with a button to revoke a live one.
A session is live, expired, ended (its host finished it with
session.end()) or revoked (an operator revoked it, or its credential was
removed). An ended or revoked session keeps that state, and when it happened,
after its original expiry passes.
Revoking a session ends it at once. Bijection refuses its token everything
from then on, and a tool call still running is refused where it next reads or
writes. An operation the session already requested, such as a refund awaiting
review, stays requested.
Limits
- A session is never given a marking’s pass: an object that carries a marking refuses the session unless one of its roles confers that pass.
- In an app with a staff directory, a session cannot read people, so a tool cannot return a staff member’s name.
- Up to four
ancestorRolesin an endpoint. - Up to 16 endpoints in a module, 32 tools in an endpoint and 24 credentials in a deployment.
- A session cannot keep working for a signed-in person after that person’s own session ends.