Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ DIRECTUS_URL=https://marketing-directus-url.com
GOOGLE_TAG_MANAGER_ID=GTM-PTLT3GH
POSTHOG_API_HOST=https://directus.io/ingest
POSTHOG_API_KEY=phc_secret_key_here
NUXT_PUBLIC_SITE_URL=https://directus.io
NUXT_PUBLIC_SITE_URL=https://directus.com
# Optional. Fine-grained PAT, public repos read-only. Required for code search and raises GitHub raw rate limits.
# GITHUB_TOKEN=github_pat_...
10 changes: 5 additions & 5 deletions content/mcp-help.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This is the **docs MCP server**, which exposes this documentation site to AI cli
## Server URL

```
https://directus.io/docs/mcp
https://directus.com/docs/mcp
```

Transport: streamable HTTP. No authentication required.
Expand All @@ -39,7 +39,7 @@ For clients without a one-click installer, add the server to your MCP config.
### Claude Code

```bash
claude mcp add --transport http directus-docs https://directus.io/docs/mcp
claude mcp add --transport http directus-docs https://directus.com/docs/mcp
```

### Claude Desktop
Expand All @@ -51,15 +51,15 @@ Edit `claude_desktop_config.json`:
"mcpServers": {
"directus-docs": {
"type": "http",
"url": "https://directus.io/docs/mcp"
"url": "https://directus.com/docs/mcp"
}
}
}
```

### Codex / Windsurf / other HTTP-MCP clients

Point them at `https://directus.io/docs/mcp` with transport set to `http` (sometimes called `streamable-http`).
Point them at `https://directus.com/docs/mcp` with transport set to `http` (sometimes called `streamable-http`).

## Available tools

Expand All @@ -84,7 +84,7 @@ The assistant should call `search-docs` or `list-docs`, then `get-doc` to read t

## Troubleshooting

- **Connection refused or 404** - confirm the URL is exactly `https://directus.io/docs/mcp` (note the `/docs` prefix).
- **Connection refused or 404** - confirm the URL is exactly `https://directus.com/docs/mcp` (note the `/docs` prefix).
- **Tools not showing up** - restart your MCP client after adding the server. Some clients only load tools at startup.
- **Search returns nothing** - `search-docs` is case-insensitive but does keyword match. Try fewer or broader terms.

Expand Down
1 change: 1 addition & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export default defineNuxtConfig({
typesenseUrl: process.env.TYPESENSE_URL,
typesensePublicApiKey: process.env.TYPESENSE_PUBLIC_API_KEY,
typesenseCollection,
siteUrl: process.env.NUXT_PUBLIC_SITE_URL,
},
directusUrl: process.env.DIRECTUS_URL,
},
Expand Down
5 changes: 3 additions & 2 deletions server/mcp/tools/get-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { queryCollection } from '@nuxt/content/server';
import { useEvent } from 'nitropack/runtime';
import { z } from 'zod';

const SITE_ORIGIN = 'https://directus.io';
const BASE_PATH = '/docs';

export default defineMcpTool({
Expand All @@ -19,6 +18,8 @@ export default defineMcpTool({
cache: '10m',
handler: async ({ path }) => {
const event = useEvent();
const config = useRuntimeConfig();
const siteOrigin = config.public.siteUrl.replace(/\/$/, '');
const normalized = path.startsWith('/') ? path : `/${path}`;

const page = await queryCollection(event, 'content')
Expand All @@ -34,7 +35,7 @@ export default defineMcpTool({
path: page.path,
description: page.description ?? '',
content: page.rawbody ?? '',
url: `${SITE_ORIGIN}${BASE_PATH}${page.path}`,
url: `${siteOrigin}${BASE_PATH}${page.path}`,
};
},
});
5 changes: 3 additions & 2 deletions server/mcp/tools/list-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useEvent } from 'nitropack/runtime';
import { z } from 'zod';
import { docsSections } from '#shared/utils/docsSections';

const SITE_ORIGIN = 'https://directus.io';
const BASE_PATH = '/docs';

const allPrefixes = Array.from(new Set(docsSections.flatMap(s => s.prefixes))).sort();
Expand All @@ -26,6 +25,8 @@ export default defineMcpTool({
cache: '10m',
handler: async ({ pathPrefix, limit }) => {
const event = useEvent();
const config = useRuntimeConfig();
const siteOrigin = config.public.siteUrl.replace(/\/$/, '');
let query = queryCollection(event, 'content')
.where('path', 'NOT LIKE', '%/.%')
.where('path', 'NOT LIKE', '%/_partials/%')
Expand All @@ -41,7 +42,7 @@ export default defineMcpTool({
title: row.title,
path: row.path,
description: row.description ?? '',
url: `${SITE_ORIGIN}${BASE_PATH}${row.path}`,
url: `${siteOrigin}${BASE_PATH}${row.path}`,
}));
},
});
4 changes: 2 additions & 2 deletions server/mcp/tools/search-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { docsSections } from '#shared/utils/docsSections';
import { frameworks } from '#shared/utils/frameworks';
import { parseTypesenseUrl } from '#shared/utils/parseTypesenseUrl';

const SITE_ORIGIN = 'https://directus.io';
const BASE_PATH = '/docs';

const sectionIds = docsSections.map(s => s.id) as [string, ...string[]];
Expand Down Expand Up @@ -50,6 +49,7 @@ export default defineMcpTool({
cache: '5m',
handler: async ({ query, section, framework, limit }) => {
const config = useRuntimeConfig();
const siteOrigin = config.public.siteUrl.replace(/\/$/, '');

if (!config.public.typesenseUrl || !config.public.typesensePublicApiKey || !config.public.typesenseCollection) {
throw createError({ statusCode: 503, message: 'Search backend not configured' });
Expand Down Expand Up @@ -93,7 +93,7 @@ export default defineMcpTool({
const rawUrl = doc.url || `${docPath}${doc.anchor ? `#${doc.anchor}` : ''}`;
const url = rawUrl.startsWith('http')
? rawUrl
: `${SITE_ORIGIN}${rawUrl.startsWith('/') ? '' : BASE_PATH}${rawUrl}`;
: `${siteOrigin}${rawUrl.startsWith('/') ? '' : BASE_PATH}${rawUrl}`;
return {
title: doc.search_title || doc.title || '',
heading: doc.heading,
Expand Down
Loading