Note: This project is unrelated to agno-agi/agno (Python agent framework).
A reliability bridge that translates MCP tool servers into an OpenAI-compatible tools interface with deterministic behavior under failures.
Point agno at any MCP server and immediately call it via an OpenAI-style POST /v1/chat/completions flow, with a canonical error contract that agents can reliably interpret.
- OpenAI-Compatible API — Drop-in replacement for tool calling workflows
- Canonical Error Contract — 8 deterministic error classes with retry guidance
- Pagination Normalization — Opaque cursor-based pagination for all list operations
- Idempotency Support — Safe retries for mutations with
X-Idempotency-Key - Auth Handling — Bridge-level credentials or per-request passthrough
- Trace Mode — Side-by-side request/response debugging
- Conformance Reports — README-ready markdown + CI-friendly JSON
# Install dependencies
npm install
# Build
npm run build
# Start the bridge
node dist/cli.js bridge --url http://localhost:3000
# Or with npx (when published)
npx agno-relay bridge --url http://localhost:3000Output:
🚀 Bridge ready
Endpoint: http://localhost:3847/v1/chat/completions
Upstream: http://localhost:3000
Capabilities:
• Streaming: unsupported
• Pagination: cursor-based
• Errors: canonical
• Auth: bridge-level
agno-relay bridge --url <mcp_server_url> [options]| Option | Description | Default |
|---|---|---|
--url <url> |
MCP server URL (required) | — |
--port <number> |
Local port | 3847 |
--allow-auth-passthrough |
Forward Authorization header | false |
--trace |
Enable debug output | false |
agno-relay report [options]| Option | Description | Default |
|---|---|---|
--format <format> |
Output format (markdown or json) |
markdown |
OpenAI-compatible chat completions endpoint with tool calling support.
Request:
{
"model": "gpt-4",
"messages": [
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {
"name": "list_repos",
"arguments": "{\"org\": \"acme\"}"
}
}
]
}
]
}Response:
{
"choices": [
{
"message": {
"role": "assistant",
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {
"name": "list_repos",
"arguments": "{\"result\": ...}"
}
}
]
}
}
]
}Health check endpoint.
{"status": "ok"}Bridge capabilities.
{
"streaming": false,
"pagination": "cursor",
"errors": "canonical",
"auth": "bridge-level"
}Every failure returns a structured error envelope:
{
"error": {
"class": "rate_limit",
"retryable": true,
"suggested_backoff_ms": 2500,
"message": "GitHub API rate limit exceeded.",
"action": "wait_and_retry",
"context": {
"source": "upstream",
"upstream_code": 429,
"reset_at": 1738491000
}
}
}| Class | HTTP Status | Retryable | Action |
|---|---|---|---|
auth |
401 | No | fix_credentials |
permission |
403 | No | check_permissions |
invalid_args |
400, 422 | No | fix_arguments |
not_found |
404 | No | not_applicable |
conflict |
409 | No | not_applicable |
rate_limit |
429 | Yes | wait_and_retry |
transient |
502, 503, 504 | Yes | retry |
timeout |
— | Depends | not_applicable |
- Read-only operations: Always retryable for
rate_limitandtransient - Mutations without
X-Idempotency-Key: Not retryable - Mutations with
X-Idempotency-Key: Retryable forrate_limitandtransient
List operations return a normalized pagination format:
{
"data": [
{"id": 1, "name": "repo-a"},
{"id": 2, "name": "repo-b"}
],
"pagination": {
"has_more": true,
"cursor": "eyJwYWdlIjoyfQ=="
}
}The cursor is opaque — pass it back to continue iteration until has_more is false.
Set credentials via environment variables:
export GITHUB_TOKEN=ghp_xxxx
# or
export MCP_AUTH_TOKEN=your-token
agno-relay bridge --url http://localhost:3000Enable forwarding of Authorization header from incoming requests:
agno-relay bridge --url http://localhost:3000 --allow-auth-passthroughThen include the header in your requests:
curl -H "Authorization: Bearer ghp_xxxx" \
http://localhost:3847/v1/chat/completionsMutation tools (create, update, delete, etc.) include a warning in their description:
⚠️ Not idempotent: do not retry without verifying state. Provide X-Idempotency-Key to enable safe retries.
Enable detailed request/response logging:
agno-relay bridge --url http://localhost:3000 --traceOutput shows side-by-side comparison:
═══ TRACE ═══
OpenAI Request:
{"model":"gpt-4","messages":[...]}
MCP Request(s):
list_repos({"org":"acme"})
MCP Response(s):
{"items":[...],"nextPageToken":"..."}
OpenAI Response:
{"choices":[...]}
═════════════
All sensitive values are automatically redacted.
Generate a conformance report for your README:
agno-relay reportOutput:
## Conformance Report
[](https://github.com/agno/report)
**Score:** 100/100
**Adapter:** agno-relay
**Last verified:** 2024-01-15T10:30:00.000Z
### Capability matrix
| Check | Status |
|-------|--------|
| schema_validity | ✅ pass |
| canonical_error_wrapping | ✅ pass |
| pagination_normalization | ✅ pass |
| auth_behavior | ✅ pass |
| determinism | ✅ pass |For CI pipelines:
agno-relay report --format jsonconst response = await fetch('http://localhost:3847/v1/chat/completions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'gpt-4',
messages: [{
role: 'assistant',
content: null,
tool_calls: [{
id: 'call_1',
type: 'function',
function: { name: 'list_repos', arguments: '{"org":"acme"}' }
}]
}]
})
});
const data = await response.json();
console.log(data.choices[0].message.tool_calls);import requests
response = requests.post(
'http://localhost:3847/v1/chat/completions',
json={
'model': 'gpt-4',
'messages': [{
'role': 'assistant',
'content': None,
'tool_calls': [{
'id': 'call_1',
'type': 'function',
'function': {'name': 'list_repos', 'arguments': '{"org":"acme"}'}
}]
}]
}
)
data = response.json()
print(data['choices'][0]['message']['tool_calls'])# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Development mode
npm run devsrc/
├── cli.ts # CLI entry point
├── server.ts # Express server
├── commands/ # CLI commands
├── mcp/ # MCP client wrapper
├── handlers/ # Request handlers
├── errors/ # Canonical error contract
├── translation/ # MCP → OpenAI translation
├── pagination/ # Cursor normalization
├── idempotency/ # Idempotency handling
├── auth/ # Authentication
├── logging/ # Redacted logging
├── trace/ # Trace mode
├── output/ # CLI output formatting
└── report/ # Conformance reports
ISC