Skip to content
Indus LeveL
AI Agents MCP RFC 9727 Cloudflare SEO

Achieving 100% AI Agent Readiness: A Guide to Modern Web Discovery

How we optimized blog.induslevel.com for AI crawlers, LLMs, and autonomous agents by implementing RFC 9727 API Catalogs, Model Context Protocol (MCP), and Content Signals.

2 min read
Holographic data mesh illustrating AI agent discoverability, MCP server cards, and structured JSON metadata endpoints

The web is evolving from a human-only interface to a hybrid ecosystem shared with autonomous AI agents, Large Language Models (LLMs), and smart crawlers. To thrive in this new era, websites must provide structured, machine-readable metadata alongside human-readable HTML.

This post details how we achieved a perfect 100/100 Level 5 Agent-Native score on IsItAgentReady.com by implementing emerging web standards on our static Astro + Cloudflare architecture.

IsItAgentReady 100% Level 5 Agent-Native Score

Core Agent Readiness Pillars

1. Discoverability & Content Signals (robots.txt)

AI crawlers require explicit permissions and structured maps to index content responsibly.

  • Sitemap Integration: Explicitly declaring Sitemap: https://blog.induslevel.com/sitemap-index.xml for rapid discovery.
  • AI Content Signals (RFC draft): Adding Content-Signal: ai-train=no, search=yes, ai-input=no to define exact post-access usage rules.
  • API Route Protection: Preventing bot pollution by disallowing /api/ endpoints.
User-agent: *
Allow: /

# AI Content Usage Permissions (RFC draft)
Content-Signal: ai-train=no, search=yes, ai-input=no

# Block API routes
Disallow: /api/

Sitemap: https://blog.induslevel.com/sitemap-index.xml

Agents rely on standard HTTP headers to navigate site structure without scraping DOM trees.

  • RFC 8288 Headers: Configuring public/_headers to expose Link: <https://blog.induslevel.com/rss.xml>; rel="alternate" and rel="sitemap".
  • Identity Anchoring: Associating authorship via rel="author" pointing to verified identity profiles.

3. API Catalog Discovery (RFC 9727)

Autonomous agents need to discover available API surfaces programmatically before attempting execution. Serving /.well-known/api-catalog with application/linkset+json.

import type { APIRoute } from 'astro';

export const GET: APIRoute = async () => {
  const linkset = {
    "linkset": [
      {
        "anchor": "https://blog.induslevel.com/api/newsletter",
        "service-doc": "https://blog.induslevel.com/contact"
      }
    ]
  };

  return new Response(JSON.stringify(linkset), {
    headers: { 'Content-Type': 'application/linkset+json' },
  });
};

4. A2A Agent Card & MCP Discovery

Exposing application capabilities directly to AI assistants like Claude and Google Antigravity.

// src/pages/.well-known/agent-card.json.ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async () => {
  const card = {
    "name": "Indus LeveL Blog Agent",
    "version": "1.0.0",
    "description": "Autonomous technical blog publishing agent and n8n workflow interface for Indus LeveL.",
    "supportedInterfaces": [
      {
        "url": "https://n8n-server.induslevel.com/webhook/65dad80c-ccce-4d38-992e-bb7f8b4753e5",
        "transportProtocol": "http"
      }
    ],
    "capabilities": [
      {
        "id": "cap-drafting",
        "name": "Article Drafting",
        "description": "Receives topic suggestions and generates technical blog post stubs via n8n workflows."
      }
    ],
    "skills": [
      {
        "id": "skill-technical-writing",
        "name": "Technical Guide Generation",
        "description": "Drafts expert guides on Linux hardening, virtualization, and cloud security."
      }
    ]
  };

  return new Response(JSON.stringify(card), {
    headers: { 'Content-Type': 'application/json' },
  });
};

5. WebMCP Client-Side Tool Registration

Injecting client-side tool declaration scripts to expose our n8n drafting webhook directly to visiting LLM browser sessions.

<script>
  function initWebMCP() {
    if (navigator.modelContext && typeof navigator.modelContext.provideContext === 'function') {
      navigator.modelContext.provideContext({
        tools: [
          {
            name: 'request_article_draft',
            description: 'Submit a topic suggestion to Waqar Azeem\'s n8n automation pipeline to draft a new technical guide stub.',
            inputSchema: {
              type: 'object',
              properties: {
                topic: { type: 'string', description: 'The technical topic or system setup you want a guide for.' },
                level: { type: 'string', enum: ['Beginner', 'Intermediate', 'Advanced'], default: 'Intermediate' }
              },
              required: ['topic']
            },
            execute: async (args) => { ... }
          }
        ]
      });
    }
  }
  document.addEventListener('astro:page-load', initWebMCP);
  initWebMCP();
</script>

The Content Negotiation Journey: Bypassing Cloudflare Caching & WAF

Implementing Accept: text/markdown content negotiation so visiting AI agents receive raw markdown while human visitors see standard HTML turned out to be an incredible architectural challenge.

The Caching & Firewall Traps We Encountered

  1. Astro Middleware & Pages Interceptors Failed: We initially built an Astro middleware interceptor and Cloudflare Pages Functions (functions/[[path]].ts). However, Cloudflare's edge CDN caches static pages based only on the URL path, completely ignoring Vary: Accept headers on standard zones. Cloudflare returned cached HTML before our application code ever executed.
  2. Cloudflare WAF JS Challenges: When automated tools like curl requested the site, Cloudflare's Bot Management inspected the TLS Client Hello fingerprint (JA3/JA4). Detecting an automated client, Cloudflare intercepted the request at the edge with a JavaScript WAF challenge page, preventing access to the markdown.

The Definitive Solution: A Standalone Cloudflare Worker

To intercept requests at the very edge in front of the CDN cache, WAF rules, and Pages runtime, we deployed a standalone Cloudflare Worker (markdown-negotiation-interceptor).

Because standalone Workers execute at the absolute perimeter of Cloudflare's network, it intercepts incoming agent traffic before Bot Protection or edge caching can ever evaluate or challenge the connection!

To ensure the Worker stays 100% maintenance-free and up-to-date with newly published articles without hardcoding text or creating circular routing loops, the Worker dynamically fetches our pre-compiled /index.md endpoint with Accept: */*.

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const acceptHeader = request.headers.get("accept") || "";

    // Check if request comes from an AI agent requesting Markdown
    if (acceptHeader.includes("text/markdown")) {
      // Determine dynamic .md endpoint path
      const mdPath = (url.pathname === '/' || url.pathname === '') ? '/index.md' : `${url.pathname.replace(/\/$/, '')}.md`;
      const markdownUrl = new URL(mdPath, url.origin);
      
      // Fetch the markdown endpoint without forwarding 'Accept: text/markdown' to prevent circular routing loops
      const cleanRequest = new Request(markdownUrl, {
        method: request.method,
        headers: new Headers(request.headers)
      });
      cleanRequest.headers.set('Accept', '*/*');

      const response = await fetch(cleanRequest);
      
      if (response.ok) {
        const newHeaders = new Headers(response.headers);
        newHeaders.set("Content-Type", "text/markdown; charset=utf-8");
        newHeaders.set("x-markdown-tokens", mdPath === '/index.md' ? "150" : "500");
        return new Response(response.body, {
          status: response.status,
          headers: newHeaders
        });
      }
    }

    // Default pass-through for standard browsers (HTML)
    return fetch(request);
  }
};

Attaching the Route (With "Fail Open" Uptime Protection)

To deploy this Worker to our blog domain while guaranteeing 100% bulletproof uptime for human readers on Cloudflare's Free plan (which limits Worker executions to 100,000 per day), we configured our Worker Route with Fail open (proceed):

  • Route: blog.induslevel.com/*
  • Worker: markdown-negotiation-interceptor
  • Failure mode: Fail open (proceed)

If our blog traffic ever exceeds 100k daily visits, Cloudflare simply bypasses the Worker and continues serving the standard HTML blog to human readers without ever showing an error page!

By pairing this standalone Worker with our dynamic Astro markdown endpoints, we achieved a flawless, maintenance-free, 100% green Agent-Ready publishing platform!

Back to Blog
Share:

Follow along

Stay in the loop — new articles, thoughts, and updates.