Skip to content

AgentReady Pitfalls

Jm Rohmer edited this page Jul 18, 2026 · 3 revisions

AgentReady Pitfalls

This page records the AgentReady problems that already happened on www.arleo.eu / mcp.arleo.eu, how they were diagnosed, and what must stay true to keep the score at 100%.

2026-07-05 Regression: Auth.md Agent Registration

Symptom:

  • IsItAgentReady dropped from 100 to 93.
  • API/Auth/MCP/Skill Discovery dropped from 7/7 to 6/7.
  • The failing check was Auth.md agent registration.

Root cause:

  • auth.md still returned HTTP 200, but its machine-readable registration block was incomplete.
  • The generated metadata had lost the agent auth section needed by IsItAgentReady.
  • After restoring agent_auth_metadata, the scan still failed until identity_assertion.credential_types_supported was restored.

Required invariant:

{
  "agent_auth_metadata": {
    "identity_types_supported": ["anonymous", "identity_assertion"],
    "identity_assertion": {
      "assertion_types_supported": [
        "urn:ietf:params:oauth:token-type:id-jag"
      ],
      "credential_types_supported": [
        "urn:ietf:params:oauth:token-type:id-jag"
      ]
    }
  }
}

If either identity_assertion.assertion_types_supported or identity_assertion.credential_types_supported disappears, IsItAgentReady can fail even when OAuth discovery and MCP server card checks still pass.

Hostname Split: www vs mcp

Keep these roles separate:

  • https://www.arleo.eu is the site scanned by IsItAgentReady.
  • https://mcp.arleo.eu is the OAuth issuer and MCP server.
  • https://mcp.arleo.eu/mcp is the only JSON-RPC MCP endpoint.

Do not make / on mcp.arleo.eu behave like /authorize or /mcp. It should be a simple informational page or explicit metadata surface.

Expected values:

Field Value
OAuth issuer https://mcp.arleo.eu
MCP protected resource https://mcp.arleo.eu/mcp
Public site resource https://www.arleo.eu
MCP endpoint https://mcp.arleo.eu/mcp

Reverse Proxy Pitfall

The live setup is not a single process serving every URL.

www.arleo.eu is served through OpenResty on the host and Nginx on the Hugo VM. Static files such as /auth.md, /llms.txt, /robots.txt, and /.well-known/* may come from the Hugo static directory, not directly from the MCP server.

Before assuming a Go bug, verify the live source of truth:

curl -skD - https://www.arleo.eu/auth.md -o /tmp/auth.md
curl -skD - https://mcp.arleo.eu/auth.md -o /tmp/mcp-auth.md
curl -sk https://mcp.arleo.eu/.well-known/oauth-authorization-server | jq .
curl -sk https://mcp.arleo.eu/.well-known/oauth-protected-resource | jq .
curl -sk https://mcp.arleo.eu/.well-known/mcp/server-card.json | jq .

If www.arleo.eu/auth.md differs from mcp.arleo.eu/auth.md, check the Hugo VM static file and rebuild Hugo before changing server code.

OpenResty Include-Glob Pitfall

On the current host, OpenResty loads sites-enabled/* verbatim. A file named like a backup, for example www.arleo.eu.bak-20260713-1659, is still active if it remains inside that directory.

That exact mistake caused the 2026-07-13 public discovery regression:

  • the stale backup vhost was still loaded;
  • it reintroduced older www.arleo.eu behavior;
  • live checks showed 403 or stale discovery metadata even though the intended config had already been edited.

Operator rule:

  • keep inactive backups outside the active include path;
  • run openresty -t and read warnings, not just the exit code;
  • treat duplicate server_name warnings as production-impacting until proven otherwise.

Hugo Static Files

The Hugo VM source of truth for public static discovery files is expected to be under:

/home/jm/hugo-site/static/

Important files:

auth.md
llms.txt
robots.txt
.well-known/oauth-protected-resource
.well-known/api-catalog
.well-known/agent-skills/index.json

After editing static files on the Hugo VM, rebuild the site and verify the live URL.

Do not trust the rebuild command blindly. Validate the real file ownership first:

ssh hugo-vm 'id hugo-mcp'
ssh hugo-vm 'stat -c "%U:%G %a %n" /home/jm/hugo-site/static /home/jm/hugo-site/public /var/www/hugo'

If the documented rebuild user cannot write the Hugo output tree, the rebuild can fail with an error like chtimes ... operation not permitted while the public static discovery files remain stale.

A second, distinct cause of the same error (#521, confirmed 2026-07-18)

The check above assumes the manual sudo -u hugo-mcp rebuild path. The MCP server's own build_site tool runs Hugo as a different system user — the systemd unit's own User=mcp-hugo-server-go/Group=mcp-hugo-server-go — not hugo-mcp. build_site can fail with the exact same chtimes <site_root>/public/<file>: operation not permitted error even when ReadWritePaths in the unit file is already correct, if any individual file inside site_root/public has drifted to be owned by a different local user (observed: hugo-mcp) than the service account. chtimes (used to preserve mtimes when Hugo copies static files) requires the calling process to actually own the destination file — write permission on the containing directory is not sufficient, unlike a normal write. The tool's own error suggestion field points at ReadWritePaths, which is misleading for this specific cause and can cost real diagnosis time.

Diagnose and fix directly:

ssh hugo-vm "systemctl show -p User --value mcp-hugo-server-go"
ssh hugo-vm "find /home/jm/hugo-site/public -not -user mcp-hugo-server-go -exec ls -la {} \;"
# Fix each mismatched file:
ssh hugo-vm "sudo chown mcp-hugo-server-go:mcp-hugo-server-go <file>"

Do not chown the whole public/ tree blindly — confirm each mismatched file individually first; a bulk chown -R on a directory Hugo also serves live traffic from is a heavier-handed change than necessary for what is normally one or two drifted files.

Cloudflare Cache Pitfall

AgentReady-facing files can be cached at the edge. If live curl output does not match the VM source after a rebuild, purge only the affected URLs.

Do not print Cloudflare tokens in logs, terminal captures, issues, wiki pages, README files, or CI output.

Regression Checks

Run these before any release:

SMOKE_LIVE=1 ./scripts/check-agent-ready.sh
SMOKE_LIVE=1 ./scripts/smoke-agent-interop.sh

Useful manual checks:

curl -sk https://www.arleo.eu/auth.md | grep -E 'agent_auth_metadata|identity_assertion|credential_types_supported'
curl -sk https://mcp.arleo.eu/auth.md | grep -E 'agent_auth_metadata|identity_assertion|credential_types_supported'
curl -sk https://mcp.arleo.eu/.well-known/oauth-authorization-server | jq '.issuer, .registration_endpoint, .scopes_supported'
curl -sk https://mcp.arleo.eu/.well-known/oauth-protected-resource | jq '.resource, .authorization_servers'

Expected IsItAgentReady result for https://www.arleo.eu:

  • Overall score: 100
  • API/Auth/MCP/Skill Discovery: 7/7
  • Auth.md agent registration: pass

Related Repository Files

  • internal/server/discovery.go
  • internal/server/discovery_test.go
  • scripts/check-agent-ready.sh
  • scripts/smoke-agent-interop.sh
  • docs/agent-ready-howto.md
  • docs/examples/agent-ready/

Related GitHub Issue

  • Issue #120: [P1] Auth.md agent registration discovery regressed without identity_assertion credential types

Clone this wiki locally