---
title: "/.well-known/mcp.json returns 403 forbidden on nginx"
url: https://hostmy.blog/docs/rankready/well-known-mcp-json-403-nginx/
date: 2026-08-24
modified: 2026-08-25
lang: en
author: "Aditya Sharma"
description: "Why nginx blocks the WebMCP manifest by default, and the exact server configuration that fixes it. No plugin setting can."
word_count: 760
---

# /.well-known/mcp.json returns 403 forbidden on nginx

This page gives you the server configuration that makes `/.well-known/mcp.json` reachable on nginx. Be clear about one thing first: this is not something RankReady can fix from inside WordPress, and no plugin setting will change it. It needs a change to your web server config, applied by whoever controls the server.

## What you are seeing

You enable the [WebMCP manifest](https://hostmy.blog/docs/rankready/how-to-add-webmcp-wordpress/) in RankReady, then request the URL and get `403 Forbidden`. The response usually comes back as a bare nginx error page rather than your theme's design. Every other RankReady endpoint works: `/llms.txt`, `/llms-full.txt`, your `.md` URLs and `/okf/` all return 200.

## Why it happens

The path begins with `.well-known`, and that leading dot makes it a dotfile path. Most nginx configurations ship with a blanket rule that denies any request whose path contains a dot-prefixed segment. The rule exists to stop people fetching `.git`, `.env` and similar. It is a sensible default. It also catches the entire `/.well-known/` directory as collateral.

The status code tells you where the request stopped. A **403** means nginx refused the request itself, before PHP or WordPress ran, so RankReady was never asked to produce anything. A **404** would mean the opposite: WordPress did handle the request and found nothing, which is a plugin-side problem and a different fix.

403 is also the worse outcome to leave in place. To a scanner, 404 reads as "this site does not offer that feature", while 403 reads as an active refusal.

## Confirm the diagnosis in one command

Request a second path under the same directory, one that RankReady has nothing to do with:

`curl -I https://example.com/.well-known/mcp.json
curl -I https://example.com/.well-known/anything-here`
If both return 403, the block is on the directory, not on the file. That is your confirmation. If the first returns 403 and the second returns 404, the server is passing `/.well-known/` through and the cause lies elsewhere.

![RankReady WebMCP manifest settings under the AI Visibility tab](https://hostmy.blog/wp-content/uploads/2026/08/rr-webmcp-v2-scaled.png)Confirm the WebMCP manifest is enabled under AI Visibility, subtab webmcp, before changing server config.

## 1. Check the plugin side first

Before touching server configuration, open **RankReady > AI Visibility** and select the **WebMCP** subtab (`tab=crawlers&sub=webmcp`). Make sure the manifest is enabled and saved. There is no point fixing a server block for an endpoint that is switched off.

## 2. Add the nginx location block

Add this to the server block for your site:

`location ^~ /.well-known/ {
allow all;
default_type text/plain;
try_files $uri $uri/ /index.php?$args;
}`
Three details matter here:

- `^~` is not decoration. It gives this prefix location priority over the regular expression location that denies dotfiles. Without it, the deny rule wins and nothing changes.
- `try_files ... /index.php?$args` hands the request to WordPress when no real file exists, which is what lets RankReady generate the manifest on the fly.
- The block belongs in the site's server configuration, not in a `.htaccess` file. nginx does not read `.htaccess`.

## 3. Test the config and reload

Validate before you reload, so a typo does not take the site down:

`sudo nginx -t
sudo systemctl reload nginx`
A reload applies the new configuration without dropping connections. If `nginx -t` reports a syntax error, fix it before reloading. The running server keeps serving the old configuration until the test passes.

## 4. Retest

`curl -I https://example.com/.well-known/mcp.json`
Expect `200`. Then fetch the body and confirm it is the manifest you expect rather than an error document or your homepage HTML:

`curl https://example.com/.well-known/mcp.json`
If you get 200 but the body is your homepage, the request reached WordPress but not RankReady's handler. Go back to step 1, then re-save Settings > Permalinks.

## If you do not control the server

On managed WordPress hosting you will not have access to the nginx configuration. Open a support ticket and give them the block above verbatim, along with the sentence "please allow requests under /.well-known/ to reach PHP". Most hosts treat this as a routine request, because the same directory is used by several widely adopted web standards.

Some control panels expose a custom nginx configuration field per site. If yours does, paste the block there rather than editing files directly, so your change survives the panel regenerating its config.

## What still works while this is broken

The 403 affects one endpoint. Everything else RankReady serves lives on ordinary paths and is unaffected: the AI index at `/llms.txt`, the full corpus at `/llms-full.txt`, per-post Markdown at `/post-slug.md`, the homepage at `/index.md`, the [Open Knowledge Format](https://hostmy.blog/docs/rankready/what-is-open-knowledge-format/) bundle at `/okf/`, and your managed block in `/robots.txt`. So a 403 here is worth fixing, but it does not leave the rest of your setup unreachable while you wait on your host.