diff --git a/.gitignore b/.gitignore index 3cf48d78a..7093ddd14 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ src/components/Layout/Fonts.scss .env *Type.ts .env.development + +# Generated data files +src/data/mcp-tools.json diff --git a/contents/docs/model-context-protocol/index.mdx b/contents/docs/model-context-protocol/index.mdx index e6837aba4..b3b2f898b 100644 --- a/contents/docs/model-context-protocol/index.mdx +++ b/contents/docs/model-context-protocol/index.mdx @@ -9,6 +9,7 @@ import WindsurfSnippet from "./_snippets/windsurf.mdx" import VSCodeSnippet from "./_snippets/vscode.mdx" import ClaudeCodeSnippet from "./_snippets/claude-code.mdx" import ZedSnippet from "./_snippets/zed.mdx" +import MCPTools from '../../../src/components/Docs/MCPTools' The PostHog [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server enables your AI agents and tools to directly interact with PostHog's products. @@ -84,68 +85,7 @@ We recommend the following best practices to mitigate security risks when using Tools trigger actions on behalf of the user based on the goals and information already in the context of the LLM. Here's a list of tools we provide: -### Organization & project management - -| Tool | Purpose | -| -- | -- | -| `organizations-get` | Get the organizations the user has access to. | -| `switch-organization` | Change the active organization from the default organization. | -| `organization-details-get` | Get the details of the active organization. | -| `projects-get` | Fetches projects that the user has access to in the current organization. | -| `switch-project` | Change the active project from the default project. | -| `property-definitions` | Get event and property definitions for the project. | - -### Feature flags - -| Tool | Purpose | -| -- | -- | -| `feature-flag-get-all` | Get all feature flags in the project. | -| `feature-flag-get-definition` | Get the definition of a feature flag. | -| `create-feature-flag` | Creates a new feature flag in the project. | -| `update-feature-flag` | Update a feature flag in the project. | -| `delete-feature-flag` | Delete a feature flag in the project. | - -### Insights & analytics - -| Tool | Purpose | -| -- | -- | -| `insights-get-all` | Get all insights in the project with optional filtering. | -| `insight-get` | Get a specific insight by ID. | -| `insight-create-from-query` | Save a query as an insight. | -| `insight-update` | Update an existing insight by ID. | -| `insight-delete` | Delete an insight by ID. | -| `insight-query` | Execute a query on an existing insight to get its results/data. | -| `get-sql-insight` | Queries project's PostHog data based on a provided natural language question. | - -### Dashboards - -| Tool | Purpose | -| -- | -- | -| `dashboards-get-all` | Get all dashboards in the project with optional filtering. | -| `dashboard-get` | Get a specific dashboard by ID. | -| `dashboard-create` | Create a new dashboard in the project. | -| `dashboard-update` | Update an existing dashboard by ID. | -| `dashboard-delete` | Delete a dashboard by ID. | -| `add-insight-to-dashboard` | Add an existing insight to a dashboard. | - -### Error tracking - -| Tool | Purpose | -| -- | -- | -| `list-errors` | List errors in the project. | -| `error-details` | Get the details of an error in the project. | - -### Documentation - -| Tool | Purpose | -| -- | -- | -| `docs-search` | Search the PostHog documentation for information. | - -### LLM observability - -| Tool | Purpose | -| -- | -- | -| `get-llm-total-costs-for-project` | Fetches the total LLM daily costs for each model for a project over a given number of days. | + ## Next Steps diff --git a/gatsby/onPreBootstrap.ts b/gatsby/onPreBootstrap.ts index 0f7e65394..3cc8054ed 100644 --- a/gatsby/onPreBootstrap.ts +++ b/gatsby/onPreBootstrap.ts @@ -2,14 +2,27 @@ import { GatsbyNode } from 'gatsby' import fetch from 'node-fetch' import path from 'path' import fs from 'fs' + +import { fetchAndProcessMCPTools, writeMCPToolsToFile } from './utils/fetchMCPTools' + export const PAGEVIEW_CACHE_KEY = 'onPreBootstrap@@posthog-pageviews' +export const MCP_TOOLS_CACHE_KEY = 'onPreBootstrap@@mcp-tools' export const onPreBootstrap: GatsbyNode['onPreBootstrap'] = async ({ cache }) => { // Copy hedgehog mode assets to public folder const source = path.resolve('node_modules/@posthog/hedgehog-mode/assets') const hedgehogModeDir = path.resolve(__dirname, '../public/hedgehog-mode') fs.cpSync(source, hedgehogModeDir, { recursive: true }) - + + // Fetch and process MCP tool definitions + const mcpToolsData = await fetchAndProcessMCPTools() + writeMCPToolsToFile(mcpToolsData) + + // Cache the data if successful + if (!mcpToolsData.error && mcpToolsData.categories) { + await cache.set(MCP_TOOLS_CACHE_KEY, mcpToolsData.categories) + } + if (process.env.POSTHOG_APP_API_KEY && !(await cache.get(PAGEVIEW_CACHE_KEY))) { const pageViews: Record = {} diff --git a/gatsby/utils/fetchMCPTools.ts b/gatsby/utils/fetchMCPTools.ts new file mode 100644 index 000000000..f53bc108a --- /dev/null +++ b/gatsby/utils/fetchMCPTools.ts @@ -0,0 +1,74 @@ +import fetch from 'node-fetch' +import path from 'path' +import fs from 'fs' + +const MCP_TOOLS_URL = 'https://raw.githubusercontent.com/PostHog/mcp/refs/heads/main/schema/tool-definitions.json' + +interface MCPTool { + category?: string + summary: string +} + +interface ToolCategory { + name: string + tools: Array<{ + name: string + summary: string + }> +} + +export async function fetchAndProcessMCPTools(): Promise<{ + categories: ToolCategory[] | null + error: boolean +}> { + try { + const response = await fetch(MCP_TOOLS_URL) + + if (response.status !== 200) { + throw new Error(`Failed to fetch MCP tools: ${response.status}`) + } + + const mcpTools = (await response.json()) as Record + + // Process the tools into categories + const toolCategories: Record> = {} + + Object.entries(mcpTools).forEach(([toolName, toolDef]) => { + const category = toolDef.category || 'Uncategorized' + if (!toolCategories[category]) { + toolCategories[category] = [] + } + toolCategories[category].push({ + name: toolName, + summary: toolDef.summary, + }) + }) + + // Sort tools within each category alphabetically + Object.values(toolCategories).forEach((tools) => { + tools.sort((a, b) => a.name.localeCompare(b.name)) + }) + + // Convert to array format and sort categories + const categoriesArray = Object.entries(toolCategories) + .map(([name, tools]) => ({ name, tools })) + .sort((a, b) => a.name.localeCompare(b.name)) + + return { + categories: categoriesArray, + error: false, + } + } catch (error) { + console.error('Error fetching MCP tools:', error) + return { + categories: null, + error: true, + } + } +} + +export function writeMCPToolsToFile(data: { categories: ToolCategory[] | null; error: boolean }): void { + const mcpToolsPath = path.resolve(__dirname, '../../src/data/mcp-tools.json') + fs.mkdirSync(path.dirname(mcpToolsPath), { recursive: true }) + fs.writeFileSync(mcpToolsPath, JSON.stringify(data, null, 2)) +} diff --git a/src/components/Docs/MCPTools.tsx b/src/components/Docs/MCPTools.tsx new file mode 100644 index 000000000..dd33cd558 --- /dev/null +++ b/src/components/Docs/MCPTools.tsx @@ -0,0 +1,76 @@ +import React from 'react' +import mcpToolsData from '../../data/mcp-tools.json' + +interface Tool { + name: string + summary: string +} + +interface ToolCategory { + name: string + tools: Tool[] +} + +const MCPTools: React.FC = () => { + const { categories: toolCategories, error } = mcpToolsData as { + categories: ToolCategory[] | null + error: boolean + } + + if (error) { + return ( +
+

+ Tools unavailable. Please view the repo{' '} + + https://github.com/posthog/mcp + {' '} + to see tools. +

+
+ ) + } + + if (!toolCategories || toolCategories.length === 0) { + return ( +
+

Loading tools...

+
+ ) + } + + return ( + <> + {toolCategories.map((category) => ( +
+

{category.name}

+ + + + + + + + + {category.tools.map((tool) => ( + + + + + ))} + +
ToolPurpose
+ {tool.name} + {tool.summary}
+
+ ))} + + ) +} + +export default MCPTools