@kya-os/mcp-i
Version:
The TypeScript MCP framework with identity features built-in
147 lines (146 loc) • 4.88 kB
TypeScript
/**
* Authorization Handshake Module
*
* Orchestrates the authorization flow for MCP-I bouncer:
* 1. Check agent reputation (optional)
* 2. Verify delegation exists
* 3. Return needs_authorization error if missing
*
* This module implements the "gatekeeper" logic that determines whether
* an agent should be allowed to execute a tool or needs human authorization.
*
* Flow:
* - If delegation exists + valid → allow (fast path)
* - If delegation missing → return needs_authorization with hints
* - If reputation too low (optional) → require authorization
*
* Related: PHASE_1_XMCP_I_SERVER.md Epic 2 (Runtime Interceptor)
*/
import { NeedsAuthorizationError } from '@kya-os/contracts/runtime';
import { DelegationVerifier } from './delegation-verifier';
import { DelegationRecord } from '@kya-os/contracts/delegation';
/**
* Agent reputation data from KTA
*/
export interface AgentReputation {
/** Agent DID */
agentDid: string;
/** Reputation score (0-100) */
score: number;
/** Total interactions recorded */
totalInteractions: number;
/** Success rate (0-1) */
successRate: number;
/** Risk level assessment */
riskLevel: 'low' | 'medium' | 'high' | 'unknown';
/** Last updated timestamp */
updatedAt: number;
}
/**
* Configuration for auth handshake
*/
export interface AuthHandshakeConfig {
/** Delegation verifier instance */
delegationVerifier: DelegationVerifier;
/** Resume token store (REQUIRED to persist tokens across calls) */
resumeTokenStore: ResumeTokenStore;
/** KTA API configuration (optional, for reputation checks) */
kta?: {
apiUrl: string;
apiKey?: string;
};
/** Bouncer configuration */
bouncer: {
/** Authorization URL base (e.g., "https://agentshield.example.com/consent") */
authorizationUrl: string;
/** Resume token TTL in milliseconds (default: 10 minutes) */
resumeTokenTtl?: number;
/** Whether to require authorization for unknown/untrusted agents */
requireAuthForUnknown?: boolean;
/** Minimum reputation score to bypass authorization (0-100) */
minReputationScore?: number;
};
/** Enable debug logging */
debug?: boolean;
}
/**
* Result of auth handshake verification
*/
export interface VerifyOrHintsResult {
/** Whether authorization is granted */
authorized: boolean;
/** Delegation record (if authorized) */
delegation?: DelegationRecord;
/** needs_authorization error (if not authorized) */
authError?: NeedsAuthorizationError;
/** Agent reputation data (if available) */
reputation?: AgentReputation;
/** Reason for decision */
reason?: string;
}
/**
* Resume token store interface
*
* Stores short-lived tokens for resuming after authorization
*/
export interface ResumeTokenStore {
/**
* Create resume token
*
* @param agentDid - Agent DID
* @param scopes - Required scopes
* @param metadata - Optional metadata (user agent, IP, etc.)
* @returns Resume token string
*/
create(agentDid: string, scopes: string[], metadata?: Record<string, any>): Promise<string>;
/**
* Get resume token data
*
* @param token - Resume token
* @returns Token data or null if expired/invalid
*/
get(token: string): Promise<{
agentDid: string;
scopes: string[];
createdAt: number;
expiresAt: number;
metadata?: Record<string, any>;
} | null>;
/**
* Mark token as fulfilled (one-time use)
*
* @param token - Resume token
*/
fulfill(token: string): Promise<void>;
}
/**
* Simple in-memory resume token store (for testing/development)
*/
export declare class MemoryResumeTokenStore implements ResumeTokenStore {
private tokens;
private ttl;
constructor(ttlMs?: number);
create(agentDid: string, scopes: string[], metadata?: Record<string, any>): Promise<string>;
get(token: string): Promise<any | null>;
fulfill(token: string): Promise<void>;
clear(): void;
}
/**
* Main auth handshake function
*
* Verifies agent authorization or returns authorization hints
*
* @param agentDid - Agent DID requesting access
* @param scopes - Required permission scopes
* @param config - Auth handshake configuration
* @param resumeToken - Optional resume token from previous authorization
* @returns Verification result with delegation or auth error
*/
export declare function verifyOrHints(agentDid: string, scopes: string[], config: AuthHandshakeConfig, _resumeToken?: string): Promise<VerifyOrHintsResult>;
/**
* Helper: Check if scopes are sensitive and require authorization
*
* @param scopes - Scopes to check
* @returns true if scopes are sensitive
*/
export declare function hasSensitiveScopes(scopes: string[]): boolean;