95 lines
2.4 KiB
TypeScript
95 lines
2.4 KiB
TypeScript
export interface AgentKey {
|
|
id: string;
|
|
name: string;
|
|
key: string;
|
|
scope: 'full' | 'read_only' | 'restricted';
|
|
allowedTools?: string[];
|
|
rateLimitPerMin: number;
|
|
requestCount: number;
|
|
lastUsedAt?: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
class MCPSecurityManager {
|
|
private keys: Map<string, AgentKey> = new Map();
|
|
private authRequired: boolean = false;
|
|
|
|
constructor() {
|
|
// Default demo key
|
|
const defaultKey: AgentKey = {
|
|
id: 'key-default-demo',
|
|
name: 'Claude Desktop Agent Key',
|
|
key: 'mcp_live_sec_claude_desktop_98123',
|
|
scope: 'full',
|
|
rateLimitPerMin: 120,
|
|
requestCount: 14,
|
|
lastUsedAt: new Date().toISOString(),
|
|
createdAt: new Date().toISOString(),
|
|
};
|
|
this.keys.set(defaultKey.key, defaultKey);
|
|
}
|
|
|
|
public isAuthRequired(): boolean {
|
|
return this.authRequired;
|
|
}
|
|
|
|
public setAuthRequired(required: boolean) {
|
|
this.authRequired = required;
|
|
}
|
|
|
|
public getKeys(): AgentKey[] {
|
|
return Array.from(this.keys.values());
|
|
}
|
|
|
|
public createKey(name: string, scope: AgentKey['scope'] = 'full', rateLimitPerMin: number = 60, allowedTools?: string[]): AgentKey {
|
|
const randomHex = Math.random().toString(36).substring(2, 12) + Math.random().toString(36).substring(2, 12);
|
|
const key = `mcp_live_sec_${randomHex}`;
|
|
const id = `key-${Date.now()}`;
|
|
const agentKey: AgentKey = {
|
|
id,
|
|
name,
|
|
key,
|
|
scope,
|
|
rateLimitPerMin,
|
|
requestCount: 0,
|
|
allowedTools,
|
|
createdAt: new Date().toISOString(),
|
|
};
|
|
this.keys.set(key, agentKey);
|
|
return agentKey;
|
|
}
|
|
|
|
public revokeKey(id: string): boolean {
|
|
for (const [k, v] of this.keys.entries()) {
|
|
if (v.id === id) {
|
|
this.keys.delete(k);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public validateKey(authHeader?: string): { valid: boolean; keyObject?: AgentKey; error?: string } {
|
|
if (!this.authRequired) {
|
|
return { valid: true };
|
|
}
|
|
|
|
if (!authHeader) {
|
|
return { valid: false, error: 'Missing Authorization header' };
|
|
}
|
|
|
|
const token = authHeader.replace(/^Bearer\s+/i, '').trim();
|
|
const keyObj = this.keys.get(token);
|
|
|
|
if (!keyObj) {
|
|
return { valid: false, error: 'Invalid or revoked MCP Agent Key' };
|
|
}
|
|
|
|
keyObj.requestCount += 1;
|
|
keyObj.lastUsedAt = new Date().toISOString();
|
|
return { valid: true, keyObject: keyObj };
|
|
}
|
|
}
|
|
|
|
export const mcpSecurityManager = new MCPSecurityManager();
|