MCP Server Requirements
Your MCP (Model Context Protocol) server is where the agent's tools live. Agent77 connects to it over SSE and forwards the user's JWT so your server can authorize every request.
What Your MCP Server Needs
- SSE transport. Agent77 connects via Server-Sent Events. Your server must support the MCP SSE transport layer.
- JWT validation. Every request includes the
user's JWT in the
Authorization: Bearerheader. Validate it before executing any tool. - Tool definitions. Expose tools using the MCP
tools/listmethod. Each tool needs a name, description, and JSON Schema for its parameters.
JWT Validation
When Agent77 calls your MCP server, it forwards the JWT that was issued by your token endpoint. Your server should:
-
Extract the token from the
Authorizationheader. - Fetch your JWKS (or cache it) and verify the signature.
-
Check
aud === "chatbot"andissmatches your domain. -
Check
exphas not passed. -
Use
subas the authenticated user ID for authorization.
Python Example
import jwt
import requests
from functools import lru_cache
ISSUER = "https://app.example.com"
JWKS_URL = f"{ISSUER}/.well-known/jwks.json"
@lru_cache(maxsize=1)
def get_jwks():
return requests.get(JWKS_URL).json()
def validate_token(auth_header: str) -> dict:
"""Validate JWT and return decoded claims."""
token = auth_header.removeprefix("Bearer ").strip()
jwks = get_jwks()
# Decode header to find kid
header = jwt.get_unverified_header(token)
kid = header["kid"]
# Find matching key
key_data = next(k for k in jwks["keys"] if k["kid"] == kid)
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key_data)
return jwt.decode(
token,
public_key,
algorithms=["RS256"],
audience="chatbot",
issuer=ISSUER,
) Node.js Example
const jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");
const ISSUER = process.env.SITE_URL;
const client = jwksClient({
jwksUri: `${ISSUER}/.well-known/jwks.json`,
cache: true,
rateLimit: true,
});
async function validateToken(authHeader) {
const token = authHeader.replace("Bearer ", "").trim();
const decoded = jwt.decode(token, { complete: true });
const key = await client.getSigningKey(decoded.header.kid);
return jwt.verify(token, key.getPublicKey(), {
algorithms: ["RS256"],
audience: "chatbot",
issuer: ISSUER,
});
} Tool Definition Best Practices
- Clear descriptions. The agent reads tool descriptions to decide when to use them. Write them as if explaining to a coworker.
- Specific parameter schemas. Use
enumfor known values, adddescriptionto each property, and mark required fields. - Scoped permissions. Use the JWT
subclaim to scope data access. A tool likelist_ordersshould only return orders for the authenticated user. - Return structured data. Return JSON objects rather than strings so the agent can reason about the result.
- Fail with context. When a tool call fails, return an
error message that helps the agent recover:
{"error": "Order not found", "suggestion": "Try list_orders first"}
Example Tool Definition
{
"name": "get_order",
"description": "Retrieve details of a specific order for the current user. Returns order status, items, and tracking info.",
"inputSchema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID (e.g. ORD-12345)"
}
},
"required": ["order_id"]
}
}