@kya-os/bouncer-middleware
v0.2.1
Published
Express middleware for MCP-I proof verification and AI agent authorization using AgentShield Bouncer
Readme
@kya-os/bouncer-middleware
Express middleware for MCP-I proof verification and AI agent authorization using AgentShield Bouncer.
Features
- ✅ MCP-I Proof Verification - Cryptographically verify AI agent identity
- ✅ Delegation Validation - Enforce OAuth-style authorization grants
- ✅ Scope-based Permissions - Fine-grained access control per endpoint
- ✅ Reputation Threshold - Block low-reputation agents automatically
- ✅ Constraint Enforcement - IP whitelists, origin restrictions, time windows
- ✅ Zero Trust - Every request must prove agent identity + authorization
Installation
npm install @kya-os/bouncer-middleware expressQuick Start
import express from 'express';
import { createBouncerMiddleware } from '@kya-os/bouncer-middleware';
const app = express();
app.use(express.json());
// Protect endpoint with Bouncer
app.post(
'/api/files',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
requiredScopes: ['files:write'],
reputationThreshold: 60,
}),
(req, res) => {
// Access verified agent info
const { agentDid, scopes, reputation } = req.bouncer;
res.json({ message: 'File created', agent: agentDid });
}
);
app.listen(3000);How It Works
1. Client (AI Agent) Creates MCP-I Proof
The AI agent generates a cryptographically signed proof:
// Agent creates proof (simplified)
const proof = {
protected: base64url({ alg: 'EdDSA', typ: 'JWT' }),
payload: base64url({
sub: 'did:key:agent-123', // Agent DID
aud: 'https://api.example.com', // Your API
iat: 1234567890,
exp: 1234571490,
nonce: 'random-nonce',
scopeId: 'files:write',
delegationRef: 'delegation-uuid', // Reference to OAuth grant
}),
signature: 'ed25519-signature-bytes',
};2. Client Sends Proof with Request
curl -X POST https://api.example.com/api/files \
-H "Content-Type: application/json" \
-H "KYA-Delegation: $(echo $proof | jq -c)" \
-d '{"filename": "test.txt", "content": "Hello World"}'3. Middleware Verifies & Authorizes
createBouncerMiddleware({
apiKey: 'your-api-key',
projectId: 'your-project-id',
requiredScopes: ['files:write'],
reputationThreshold: 60,
});The middleware:
- ✅ Extracts proof from
KYA-Delegationheader - ✅ Verifies cryptographic signature with AgentShield
- ✅ Checks proof hasn't expired
- ✅ Validates delegation (OAuth-style grant)
- ✅ Enforces required scopes
- ✅ Checks agent reputation threshold
- ✅ Validates constraints (IP, origin, time windows)
- ✅ Attaches verified data to
req.bouncer
Configuration
interface BouncerConfig {
/** AgentShield API key (required) */
apiKey: string;
/** Project ID (required) */
projectId: string;
/** AgentShield API URL (optional, defaults to production) */
apiUrl?: string;
/** Minimum reputation score 0-100 (optional) */
reputationThreshold?: number;
/** Required scopes for this endpoint (optional) */
requiredScopes?: string[];
/** Custom error handler (optional) */
onError?: (error: BouncerError, req: Request) => void;
/** Enable debug logging (optional) */
debug?: boolean;
}Examples
Basic Protection
app.get(
'/api/health',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
}),
(req, res) => {
res.json({ status: 'ok', agent: req.bouncer.agentDid });
}
);Scope-based Authorization
// Read files - requires files:read scope
app.get('/api/files',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
requiredScopes: ['files:read'],
}),
(req, res) => {
res.json({ files: [...] });
}
);
// Write files - requires files:write scope
app.post('/api/files',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
requiredScopes: ['files:write'],
}),
(req, res) => {
res.json({ message: 'File created' });
}
);Reputation-based Access
// Only high-reputation agents can create payments
app.post(
'/api/payment',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
requiredScopes: ['payment:create'],
reputationThreshold: 80, // 0-100 scale
}),
(req, res) => {
const { reputation } = req.bouncer;
res.json({ message: 'Payment created', agent_reputation: reputation });
}
);Custom Error Handling
app.delete(
'/api/files/:id',
createBouncerMiddleware({
apiKey: process.env.AGENTSHIELD_API_KEY!,
projectId: process.env.AGENTSHIELD_PROJECT_ID!,
requiredScopes: ['files:delete'],
onError: (error, req) => {
console.error('Bouncer blocked request:', {
error: error.code,
message: error.message,
url: req.url,
agent: error.details?.agent_did,
});
// Optional: Log to monitoring service
// monitoring.logSecurityEvent({ ... });
},
}),
(req, res) => {
res.json({ message: 'File deleted' });
}
);Request Object Extensions
After successful verification, the middleware attaches verified data to req.bouncer:
interface BouncerRequest extends Request {
bouncer: {
/** Verified MCP-I proof payload */
proof: MCPIProofPayload;
/** Agent DID (Decentralized Identifier) */
agentDid: string;
/** Delegation information (if applicable) */
delegation?: Delegation;
/** Agent reputation score 0-100 (if checked) */
reputation?: number;
/** Granted scopes from delegation */
scopes: string[];
};
}Error Handling
The middleware returns standardized error responses:
{
"error": {
"code": "INSUFFICIENT_SCOPES",
"message": "Required scopes: files:write. Granted: files:read",
"details": {
"required": ["files:write"],
"granted": ["files:read"]
}
}
}Error Codes
| Code | Status | Description |
| ---------------------- | ------ | -------------------------------- |
| MISSING_PROOF | 401 | No MCP-I proof provided |
| INVALID_PROOF | 400 | Malformed proof structure |
| EXPIRED_PROOF | 401 | Proof has expired |
| INVALID_SIGNATURE | 401 | Signature verification failed |
| DELEGATION_NOT_FOUND | 404 | Delegation reference invalid |
| DELEGATION_EXPIRED | 403 | Delegation has expired |
| DELEGATION_REVOKED | 403 | Delegation was revoked |
| INSUFFICIENT_SCOPES | 403 | Missing required scopes |
| REPUTATION_TOO_LOW | 403 | Agent reputation below threshold |
| CONSTRAINT_VIOLATION | 403 | Violated delegation constraints |
| API_ERROR | 500 | Internal server error |
Testing with cURL
# Set environment variables
export API_KEY="your-agentshield-api-key"
export PROJECT_ID="your-project-id"
export API_URL="https://kya.vouched.id"
# Create a delegation first (requires OAuth flow in production)
DELEGATION_RESPONSE=$(curl -X POST $API_URL/api/v1/bouncer/delegations \
-H "X-API-Key: $API_KEY" \
-H "X-Project-Id: $PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"agent_did": "did:key:test-agent-123",
"scopes": ["files:read", "files:write"],
"expires_in_days": 7
}')
DELEGATION_ID=$(echo $DELEGATION_RESPONSE | jq -r '.data.delegation_id')
# Create MCP-I proof (simplified for testing)
PROOF=$(cat <<EOF | jq -c
{
"protected": "$(echo -n '{"alg":"EdDSA","typ":"JWT"}' | base64)",
"payload": "$(echo -n "{\"sub\":\"did:key:test-agent-123\",\"aud\":\"http://localhost:3000\",\"iat\":$(date +%s),\"exp\":$(($(date +%s) + 300)),\"nonce\":\"test-nonce\",\"delegationRef\":\"$DELEGATION_ID\",\"scopeId\":\"files:write\"}" | base64)",
"signature": "test-signature-for-demo"
}
EOF
)
# Test protected endpoint
curl -X POST http://localhost:3000/api/files \
-H "Content-Type: application/json" \
-H "KYA-Delegation: $PROOF" \
-d '{"filename": "test.txt", "content": "Hello World"}'TypeScript Support
Full TypeScript support with exported types:
import type {
BouncerConfig,
BouncerRequest,
MCPIProof,
MCPIProofPayload,
Delegation,
BouncerError,
} from '@kya-os/bouncer-middleware';License
MIT OR Apache-2.0
Related Packages
@kya-os/agentshield-shared- Shared types and schemas@kya-os/agentshield-express- Agent detection middleware@kya-os/agentshield-nextjs- Next.js integration
Support
- Documentation: https://docs.kya.vouched.id
- Issues: https://github.com/Know-That-Ai/agent-shield/issues
- Discord: https://discord.gg/knowthat
