import type { ApplicationService } from '@adonisjs/core/types';
import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
import type { Actor } from '../types.js';
/**
 * Runtime context a {@link McpAuthFactory} thunk receives when the MCP provider builds the configured
 * auth at boot. Carries the booted application so a driver can resolve a peer's service if it needs to.
 */
export interface McpAuthContext {
    app: ApplicationService;
}
/**
 * OAuth metadata the MCP server advertises at `/.well-known/oauth-protected-resource{path}` (RFC 9728)
 * so an MCP client can discover how to obtain a token. Omitted → the server exposes no OAuth metadata
 * endpoint and clients must authenticate another way (e.g. a static API key).
 */
export interface McpOAuthMetadata {
    /** The OAuth 2.0 / OIDC authorization server (the authkit issuer, e.g. `http://localhost:3333/oidc`). */
    issuer: string;
    /** Authorization endpoint the MCP client redirects to (e.g. `${issuer}/auth`). */
    authorizationEndpoint: string;
    /** Token endpoint the MCP client exchanges the code at (e.g. `${issuer}/token`). */
    tokenEndpoint: string;
    /** Scopes supported by the authorization server. */
    scopesSupported: string[];
    /** Human label for the protected resource. */
    resourceName: string;
}
/**
 * The `extra` of an {@link McpAuthInfo}: the SDK's open record, with the acting {@link Actor} typed.
 * A strategy of your own can carry more beside it (a session, the raw claims) without a cast, and
 * the whole object is still an SDK `AuthInfo['extra']`.
 */
export interface McpAuthExtra {
    actor: Actor;
    [key: string]: unknown;
}
/**
 * MCP `AuthInfo` with a typed acting {@link Actor} in `extra`. The MCP auth strategies
 * (`authKitAuth`/`apiKeyAuth`) and the open-mode fallback all produce this shape, so consumers can
 * read `extra.actor` without a runtime guard. It is assignable to the SDK's `AuthInfo`; going the
 * other way — the `AuthInfo` the SDK hands a request handler — narrow with `isMcpAuthInfo`, or
 * resolve the actor with `actorFromAuthInfo`, which throws when there is none.
 */
export interface McpAuthInfo extends Omit<AuthInfo, 'extra'> {
    extra: McpAuthExtra;
}
/**
 * A configured MCP auth strategy. `verify` validates a bearer token and resolves the acting {@link Actor}
 * (attached to `extra.actor` as a typed {@link McpAuthInfo}); it MUST throw when the token is
 * missing/invalid/expired. The same `AuthInfo` is surfaced to the `tools/list` / `tools/call` handlers
 * as `extra.authInfo`, so the actor the tool registry gates against is exactly the one the auth
 * strategy resolved — consumers can read it with `authInfo.extra.actor` or `actorFromAuthInfo`.
 */
export interface McpAuth {
    /** OAuth metadata to advertise, resolved lazily (the authkit peer may not be bootable until first use). */
    oauth?: McpOAuthMetadata | (() => McpOAuthMetadata | Promise<McpOAuthMetadata>);
    /**
     * Validate `token` and resolve the acting actor as a typed `McpAuthInfo`. Throws on rejection:
     * {@link McpAuthError} for a deliberate refusal (its `status` and message reach the client), any
     * other `Error` for a token this strategy does not recognize (→ `401`).
     */
    verify(token: string, context?: McpVerifyContext): Promise<McpAuthInfo>;
}
/** What the provider knows about the request a token is verified for. */
export interface McpVerifyContext {
    /**
     * The protected resource (RFC 9728 `resource`) being called, e.g. `https://app.example.com/mcp` —
     * what a token's audience must name (MCP Authorization spec, RFC 8707).
     */
    resource: string;
}
/**
 * A typed refusal from an MCP auth strategy: the token was recognized and deliberately refused (a
 * client that is not allowed on this endpoint, an account that left the tenant, a revoked grant).
 *
 * Throw it from `verify` — or from the `toActor` of `authKitAuth()` / `apiKeyAuth()` — and the
 * provider answers with its `status` and message, plus the matching `WWW-Authenticate` challenge:
 * `401` → `error="invalid_token"`, `403` → `error="insufficient_scope"`.
 *
 * Inside {@link anyOf} it is also a stop signal: a strategy that throws `McpAuthError` has claimed
 * the token, so the remaining strategies are not tried. Any other error means "not my token" and
 * the next strategy gets its turn.
 *
 * ```ts
 * authKitAuth({
 *   toActor: ({ accountId, clientId }) => {
 *     if (clientId === 'web') throw new McpAuthError('token was not issued for MCP')
 *     return { id: accountId }
 *   },
 * })
 * ```
 */
export declare class McpAuthError extends Error {
    /** HTTP status of the refusal: `401` (the token does not authenticate) or `403` (it does, but may not do this). */
    readonly status: 401 | 403;
    /**
     * The `WWW-Authenticate` error code, when not the status' default (`invalid_token` for 401,
     * `insufficient_scope` for 403) — e.g. Poppy's `sign_in_required` (§4.3).
     */
    readonly error?: McpChallengeError;
    constructor(message: string, options?: {
        status?: 401 | 403;
        error?: McpChallengeError;
        cause?: unknown;
    });
}
/** Error codes the MCP endpoint can put in its `WWW-Authenticate` challenge. */
export type McpChallengeError = 'invalid_token' | 'insufficient_scope' | 'sign_in_required';
/**
 * A configured MCP auth strategy, as a lazy thunk the provider calls at boot. Each factory lazily
 * imports / resolves its peer inside the thunk, so nothing loads until the strategy is actually selected.
 */
export type McpAuthFactory = (ctx: McpAuthContext) => McpAuth | Promise<McpAuth>;
/**
 * Resolve a `McpAuth` config value (a ready instance or a lazy factory) at provider boot.
 */
export declare function resolveMcpAuth(auth: McpAuth | McpAuthFactory, ctx: McpAuthContext): Promise<McpAuth>;
/** The `gty` authkit-server gives the access tokens it mints for a Poppy session (§6, MCP). */
export declare const POPPY_GRANT_TYPE = "poppy";
/**
 * The organization authkit bound to a grant at consent time (the active org of the session that
 * approved it). Stored on the grant as `activeOrg`.
 */
export interface AuthKitActiveOrg {
    orgId: string;
    orgSlug?: string;
    orgRole?: string;
}
/**
 * The oidc-provider `Grant` behind an access token — the authorization the user gave to a client.
 * Duck-typed: only the fields this package reads are named; the rest of the stored grant is there too.
 */
export interface AuthKitGrant {
    accountId?: string;
    clientId?: string;
    /** Set by authkit at consent when the session had an active organization. */
    activeOrg?: unknown;
    [key: string]: unknown;
}
/** What `authKitAuth()` hands `toActor` for a verified access token. */
export interface AuthKitActorInfo {
    /** The account the token was issued to. */
    accountId: string;
    /** The token's granted scopes. */
    scopes: string[];
    /** The client the token was issued to — refuse clients that should not reach MCP by throwing {@link McpAuthError}. */
    clientId: string | undefined;
    /** The grant id the token belongs to, when the provider tracks one. */
    grantId: string | undefined;
    /** The grant itself (loaded per request, so a revoked grant stops the token right away). */
    grant: AuthKitGrant | undefined;
    /** The organization authkit bound to the grant at consent — the tenant the user authorized. */
    activeOrg: AuthKitActiveOrg | undefined;
    /** Extra claims stored on the access token (`extraTokenClaims`), if any. */
    extra: Record<string, unknown> | undefined;
    /**
     * The token belongs to a **personal agent** — authkit minted it for a Personal Agent Protocol
     * (Poppy) session (`gty: 'poppy'`), not for an MCP client the user logged into. Whatever `toActor`
     * returns, the actor then also gets `personal_agent` and one `scope:<id>` role per granted scope,
     * so the personal agent gate applies: only the tools of its scopes run.
     */
    personalAgent: boolean;
}
/**
 * How `authKitAuth()` maps an access token to the MCP actor. Defaults to the account id. Throw
 * {@link McpAuthError} to refuse the token (e.g. a client that is not allowed on this endpoint).
 */
export type AuthKitActorResolver = (info: AuthKitActorInfo) => Actor | Promise<Actor>;
/** Options for {@link authKitAuth}. */
export interface AuthKitMcpAuthOptions {
    /** Scopes the authorization server advertises. Defaults to the standard authkit scopes. */
    scopes?: string[];
    /** Map a validated access token to the acting {@link Actor}. Defaults to `{ id: accountId }`. */
    toActor?: AuthKitActorResolver;
    /** Human label for the protected resource. Defaults to `'Agent MCP Server'`. */
    resourceName?: string;
    /**
     * Which tokens this endpoint accepts, by audience:
     *  - `'resource'` (default) — only a token issued for THIS server: its `aud` (RFC 8707) must be
     *    the MCP URL. A token for another resource, or one with no audience (a web login's), is
     *    refused — the MCP Authorization spec forbids accepting tokens not meant for the server.
     *  - `'any'` — skip the check (tokens from clients that do not send `resource`).
     */
    audience?: 'resource' | 'any';
}
/**
 * Authenticate MCP clients with `@adonis-agora/authkit-server`: verifies the bearer token against the
 * authkit OIDC provider's stored access tokens (`provider.AccessToken.find`) and advertises OAuth
 * metadata derived from the issuer so MCP clients can run the full OAuth login flow.
 *
 * The authkit peer is resolved lazily — the `verify`/`oauth` accessors touch the container only when
 * a request actually arrives (by then the app is fully booted and the authkit keystore/encryption
 * services are ready). `@adonis-agora/authkit-server` stays an optional dependency. Throws a clear
 * error at first use if the binding isn't resolvable (authkit not installed / provider not registered).
 */
export declare function authKitAuth(options?: AuthKitMcpAuthOptions): McpAuthFactory;
/** Resolve the MCP actor from a validated API key. Defaults to `{ id: apiKey }`. */
export type ApiKeyActorResolver = (apiKey: string) => Actor | Promise<Actor>;
/** Options for {@link apiKeyAuth}. */
export interface ApiKeyMcpAuthOptions {
    /** Static API keys clients present in `Authorization: Bearer <key>`. */
    apiKeys: string[];
    /** Map a validated API key to the acting {@link Actor}. Defaults to `{ id: apiKey }`. */
    toActor?: ApiKeyActorResolver;
}
/**
 * Authenticate MCP clients with a static list of API keys (no OAuth metadata). Intended for trusted
 * gateway / machine-to-machine integrations where the host proxies auth and this server just
 * checks the key. Keys are compared with a constant-time compare to resist timing attacks.
 */
export declare function apiKeyAuth(options: ApiKeyMcpAuthOptions): McpAuthFactory;
/**
 * Accept more than one kind of bearer token on the same MCP endpoint — e.g. OAuth access tokens from
 * MCP clients that logged in through the browser AND personal access tokens for machine integrations:
 *
 * ```ts
 * auth: anyOf(
 *   authKitAuth({ toActor }),
 *   { verify: verifyPersonalAccessToken },
 * )
 * ```
 *
 * Strategies are tried in order and the first that verifies the token wins. A strategy that throws a
 * plain `Error` passes ("not my token"); one that throws {@link McpAuthError} has claimed the token and
 * refused it, so the chain stops there with that refusal. When every strategy passes, the last error
 * is rethrown.
 *
 * OAuth metadata comes from the first strategy that exposes it, so the RFC 9728 document and the
 * `WWW-Authenticate` challenge still point MCP clients at the login flow.
 */
export declare function anyOf(...strategies: Array<McpAuth | McpAuthFactory>): McpAuthFactory;
//# sourceMappingURL=auth.d.ts.map