AIScan cover: Your MCP card on Lovable, with the Lovable name chip and three steps: pick your template, add the card file, publish and curl it.
AIScan cover: Your MCP card on Lovable, with the Lovable name chip and three steps: pick your template, add the card file, publish and curl it.
AI Readiness

How to publish /.well-known/mcp/server-card.json on Lovable

Publish /.well-known/mcp/server-card.json on Lovable: a file in public/ for either template, or an escaped TanStack Start route, with real curl output.

AAIScan Content Team 7 Oct 2026 5 min read
#MCP#server card#Lovable#well-known

This guide covers P2 · Capabilities — for Lovable.

Table of contents

Lovable builds two kinds of project, and an MCP server card lives in a different place in each. Get the template wrong and you either edit a file that never ships or create a route that answers 404. This guide covers the card for check P2 on both templates. I built a TanStack Start app and a React + Vite app, and every response below was captured from a running server.

The card is the JSON document at /.well-known/mcp/server-card.json that tells an agent where your MCP server lives. Its schema is still a draft, so read Publish an MCP Server Card So Agents Can Find Your Tools first. This post is only the Lovable mechanics for check P2, which AIScan grades.

Quick summary

If your Lovable project is on...Do thisTime
React + Vite (older projects)Add public/.well-known/mcp/server-card.json and publish5 min
TanStack Start (new apps since 13 May 2026), fixed cardSame file in public/5 min
TanStack Start, card with CORS and cache headersAdd the route file src/routes/[.]well-known.mcp.server-card[.]json.ts10 min
Either, still on a preview or lovable.app workspace URLConnect a custom domain before judging the resultvaries

Check first: run npx aiscan-cli yoursite.com and read check P2 in the Capabilities group.

Which Lovable template are you on?

According to Lovable's SEO and AI search docs, apps created from 13 May 2026 use TanStack Start with server-side rendering, and older apps use React + Vite. Look for routeTree.gen.ts under src/: if it exists, you are on TanStack Start. A plain index.html at the project root with a src/main.tsx means React + Vite. Lovable also documents an upgrade path to TanStack Start.

Option 1: a file in public/

This works on both templates. Ask the Lovable agent in the project chat to create public/.well-known/mcp/server-card.json with your card:

{
  "serverInfo": { "name": "example-mcp", "version": "1.0.0" },
  "description": "Search the example catalog",
  "transport": { "type": "streamable-http", "url": "https://example.com/mcp" },
  "tools": [{ "name": "search", "description": "Search the catalog" }]
}

Replace the example values with your real server name, endpoint and tools. The field names follow the shape in AIScan's own P2 guidance and are a convention, not a ratified schema.

On a React + Vite build, vite build copied the file untouched to dist/.well-known/mcp/server-card.json, and vite preview answered with 200 and application/json. On TanStack Start the dev server served the same file as application/json with Cache-Control: no-cache. You cannot set other headers on a plain file from the project code.

Option 2: a TanStack Start server route

Use this when the card needs CORS headers for browser-based clients. The folder trick from other frameworks does not work here. TanStack Router reads a . in a file name as a path separator, so each literal dot has to be escaped. Per the file naming conventions, square brackets escape special characters, and script[.]js.tsx becomes /script.js.

Create src/routes/[.]well-known.mcp.server-card[.]json.ts:

import { createFileRoute } from '@tanstack/react-router'

const card = {
  serverInfo: { name: 'example-mcp', version: '1.0.0' },
  description: 'Search the example catalog',
  transport: { type: 'streamable-http', url: 'https://example.com/mcp' },
}

export const Route = createFileRoute('/.well-known/mcp/server-card.json')({
  server: {
    handlers: {
      GET: () =>
        Response.json(card, {
          headers: {
            'Access-Control-Allow-Origin': '*',
            'Cache-Control': 'public, max-age=3600',
          },
        }),
    },
  },
})

I tested this on @tanstack/react-start 1.168.60, @tanstack/react-router 1.170.41 and Vite 8.3.3. The generated route tree listed the path /.well-known/mcp/server-card.json, and the endpoint returned 200, application/json, access-control-allow-origin: * and cache-control: public, max-age=3600. A request with a trailing slash also returned 200.

The one-character mistake

Leave the second dot unescaped and you get a different URL. I renamed the file to [.]well-known.mcp.server-card.json.ts and the route tree registered /.well-known/mcp/server-card/json. That path returned 200. The path AIScan checks, /.well-known/mcp/server-card.json, returned 404. Nothing errors at build time, so the file looks right and the card is missing. Open routeTree.gen.ts and read the path: line for your route.

Publish, then test the live domain

A preview is not the live site. Lovable's docs say branded workspace URLs are never indexable, and that you should connect a custom domain to build search presence. Publish the project, then test the domain agents will use. How hosting serves files to crawlers is described on Lovable's hosting page.

Verify the card

Run AIScan first:

npx aiscan-cli yoursite.com

Find P2 · MCP Server Card in the Capabilities group. It should pass. By hand, one request does the same job:

curl -si https://yoursite.com/.well-known/mcp/server-card.json

Expected output for the route version, trimmed:

HTTP/2 200
content-type: application/json
access-control-allow-origin: *
cache-control: public, max-age=3600

{"serverInfo":{"name":"example-mcp","version":"1.0.0"}, ...}

For the public/ file you will see 200 and application/json without the two custom headers.

When the card still fails

  • 404 on the route version. The file name has an unescaped dot, or the dev server has not regenerated routeTree.gen.ts. Check the path: line.
  • 200 with an HTML body. A React + Vite single-page app answers unknown paths with the app shell. In vite preview, a misspelled server-card.jsn returned 200 with text/html. Look at content-type and the first bytes of the body, never only the status code. I did not test Lovable's own host for this behavior, so check it with curl.
  • Works on the preview, fails on your domain. The project was edited but not published again.

Where to go next

Run npx aiscan-cli yoursite.com, confirm check P2, then browse the other fixes in the AIScan guides. The capabilities checks reference lists P1 to P4 and E2. If your project also lacks a feed, the RSS guide for Lovable covers the same template split, and the Lovable page lists every guide for the platform. The Next.js version of this guide covers the same check on another framework.

Frequently asked questions

Where does the MCP server card go in a Lovable project?

Put it at public/.well-known/mcp/server-card.json on either template, or on TanStack Start add a server route file named [.]well-known.mcp.server-card[.]json.ts under src/routes. Both serve /.well-known/mcp/server-card.json.

How do I know whether my Lovable project is on TanStack Start or React + Vite?

Lovable's docs say apps created from 13 May 2026 use TanStack Start and older apps use React + Vite. A routeTree.gen.ts file under src/ means TanStack Start.

Why does my card return 404 after I added a TanStack route file?

The file name probably has an unescaped dot. server-card.json.ts registers /server-card/json, not /server-card.json. Write server-card[.]json.ts and read the path line in routeTree.gen.ts.

Why does the card URL return 200 but AIScan still fails check P2?

A single-page app can answer any unknown path with its HTML shell and a 200 status. Check that content-type is application/json and that the body starts with a JSON object.

Why does the card work in preview but not on my domain?

The latest edit was probably not published. Publish the project again, then request the card on the custom domain agents will use.

Do I need the TanStack route, or is a file in public/ enough?

A file in public/ is enough to pass a presence check. Use the route when you want to send CORS and cache headers from your own code, which a plain file cannot do.

Does the server card replace server/discover or the MCP Registry?

No. They answer different questions. The card is a static document a crawler reads over plain HTTP, and the registry is a separate listing. The linked server card guide explains both.

Which fields should the card contain?

The shape in AIScan's P2 guidance uses serverInfo, description, transport and tools. The schema is still a draft, so treat the field names as a convention and keep the card small and accurate.

Related guides