@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
69 lines • 3.7 kB
TypeScript
import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import type { RolesPolicy } from '../spi/roles-policy.js';
import { ToolRegistry } from '../tool-registry.js';
import type { Actor, ToolSpec } from '../types.js';
import type { McpToolDescriber } from './define_config.js';
/**
* Runtime context a MCP handler synthesizes for {@link ToolRegistry.invoke}: the acting {@link Actor}
* comes from the verified auth, and the run/request ids from the MCP request so tool traces map back
* to the MCP session.
*/
export interface McpToolContextOptions {
/** How the actor is resolved from the transport's verified auth info. */
actorFromAuth: (authInfo: AuthInfo | undefined) => Actor;
/** How run/thread/request ids are derived. Defaults to the MCP session + request ids. */
idsFromRequest?: (sessionId: string | undefined, requestId: string | number | undefined) => {
threadId: string;
runId: string;
requestId: string;
};
}
/** Options for {@link createMcpServer}. */
export interface CreateMcpServerOptions extends McpToolContextOptions {
/** Server name reported in the initialize handshake. */
name: string;
/** Server version reported in the initialize handshake. */
version: string;
/** Instructions for the client's model, sent in the initialize result. */
instructions?: string;
/** Title and MCP annotations per tool; default `readOnlyHint` from the tool's kind. */
describeTool?: McpToolDescriber;
/** The agent tool registry to expose. */
registry: ToolRegistry;
/** Tool authorization gate (role re-check happens per call, defense-in-depth). */
policy: RolesPolicy;
/** Optional allow-list restricting which tools are exposed. */
allowedTools?: string[];
/**
* What to do with `action` tools. Defaults to `'refuse'`: they are neither listed nor callable.
*
* An `action` is HITL-gated in the loop — a human approves it before it runs. An MCP caller has
* no human, so honouring that gate is impossible and the tool stays off the surface. `'execute'`
* is a deployment saying it accepts an unapproved actor running every `action` its roles reach.
*/
actions?: 'refuse' | 'execute';
}
/** Whether this tool may be reached over MCP at all — the same answer for listing and for calling. */
export declare function isExposable(spec: {
kind: string;
presentation?: ToolSpec['presentation'];
} | undefined, actions: 'refuse' | 'execute'): boolean;
/**
* Build a low-level MCP `Server` that exposes the agent's {@link ToolRegistry} over the wire:
*
* - `tools/list` → `registry.definitionsFor(actor, policy, allowedTools)` — the tools the acting
* actor's roles permit (fail-closed via the same `RolesPolicy` the agent loop uses), converted to
* MCP `Tool` descriptors with JSON-Schema inputs.
* - `tools/call` → `registry.invoke(name, args, ctx, policy)` — role re-check + input re-validation
* before the handler runs (the registry's own defense-in-depth), so a stale tool list can never
* bypass the gate.
*
* The acting actor comes from the verified auth's `extra.authInfo`: the MCP auth strategies
* (`authKitAuth`/`apiKeyAuth`) attach it to `extra.actor` as a typed `McpAuthInfo`, and `actorFromAuth`
* resolves it (e.g. with the library's `actorFromAuthInfo` helper) before the gate runs.
*
* Use this in the MCP provider (one server per session, connected to that session's transport).
*/
export declare function createMcpServer(options: CreateMcpServerOptions): Server;
//# sourceMappingURL=server.d.ts.map