diff --git a/api/mcp/tools/docs.py b/api/mcp/tools/docs.py index 6e81cca..f722082 100644 --- a/api/mcp/tools/docs.py +++ b/api/mcp/tools/docs.py @@ -62,8 +62,10 @@ def _snippet(content: str, query_tokens: list[str], width: int = 240) -> str: if idx >= 0: start = max(0, idx - width // 2) end = min(len(content), start + width) - return ("…" if start > 0 else "") + content[start:end].strip() + ( - "…" if end < len(content) else "" + return ( + ("…" if start > 0 else "") + + content[start:end].strip() + + ("…" if end < len(content) else "") ) return content[:width].strip() + ("…" if len(content) > width else "") @@ -83,9 +85,7 @@ async def search_dograh_docs(query: str, limit: int = 5) -> list[dict]: return [] scores = bm25.get_scores(tokens) - ranked = sorted( - zip(scores, docs), key=lambda pair: pair[0], reverse=True - )[:limit] + ranked = sorted(zip(scores, docs), key=lambda pair: pair[0], reverse=True)[:limit] return [ { diff --git a/api/mcp/tools/workflows.py b/api/mcp/tools/workflows.py index d22d92b..c697baa 100644 --- a/api/mcp/tools/workflows.py +++ b/api/mcp/tools/workflows.py @@ -33,8 +33,10 @@ async def list_workflows(status: str | None = None) -> list[dict]: async def get_workflow(workflow_id: int) -> dict: """Fetch a single agent by id, including its current published definition.""" user = await authenticate_mcp_request() - workflow = await db_client.get_workflow_by_id(workflow_id) - if not workflow or workflow.organization_id != user.selected_organization_id: + workflow = await db_client.get_workflow( + workflow_id, organization_id=user.selected_organization_id + ) + if not workflow: raise HTTPException(status_code=404, detail=f"Workflow {workflow_id} not found") current = workflow.current_definition diff --git a/docs/docs.json b/docs/docs.json index 3a036e8..4a5ec40 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -104,6 +104,12 @@ "integrations/telephony/webhooks", "integrations/telephony/custom" ] + }, + { + "group": "Integrations", + "pages": [ + "integrations/mcp" + ] } ] }, diff --git a/docs/integrations/mcp.mdx b/docs/integrations/mcp.mdx new file mode 100644 index 0000000..61d7b57 --- /dev/null +++ b/docs/integrations/mcp.mdx @@ -0,0 +1,70 @@ +--- +title: "MCP Server" +description: "Connect Claude and other AI assistants to your Dograh workspace via the Model Context Protocol" +--- + +## Overview + +Dograh exposes an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that lets AI assistants like Claude Code, Claude Desktop, and Cursor access your workspace and documentation. Once connected, an assistant can list your agents, fetch agent definitions, and search Dograh docs on your behalf. + +## Prerequisites + +- A Dograh API key. Generate one at [`/api-keys`](https://app.dograh.com/api-keys) (or `http://localhost:3010/api-keys` for self-hosted). See [API Keys](/configurations/api-keys). +- Your Dograh MCP endpoint: + - Hosted: `https://app.dograh.com/api/v1/mcp/` + - Self-hosted: `/api/v1/mcp/` + +The endpoint is also shown in **Platform Settings → MCP Server** inside the Dograh UI. + +## Claude Code + +Register Dograh as an MCP server with the Claude Code CLI: + +```bash +claude mcp add --transport http dograh https://app.dograh.com/api/v1/mcp/ \ + --header "X-API-Key: YOUR_API_KEY" +``` + +Replace `YOUR_API_KEY` with the key you generated. For self-hosted deployments, swap the URL for your backend. + +Verify the server is connected: + +```bash +claude mcp list +``` + +## Claude Desktop + +Open Claude Desktop's config file (`claude_desktop_config.json`) and add the `dograh` entry under `mcpServers`: + +```json +{ + "mcpServers": { + "dograh": { + "url": "https://app.dograh.com/api/v1/mcp/", + "headers": { + "X-API-Key": "YOUR_API_KEY" + } + } + } +} +``` + +Restart Claude Desktop after saving. The Dograh tools should appear in the tool picker. + +## Cursor and other MCP clients + +Any MCP client that supports Streamable HTTP transport can connect with the same URL and header. Paste the configuration above into your client's MCP settings file and replace `YOUR_API_KEY`. + +## Available tools + +Once connected, your AI assistant can: + +- `list_workflows` — list agents in your workspace +- `get_workflow` — fetch an agent's definition by ID +- `search_dograh_docs` — search Dograh documentation +- `fetch_dograh_doc` — retrieve a specific doc page + + +The API key controls which workspace the assistant sees. Treat it like any other credential — do not commit it to source control or paste it into shared chats. + diff --git a/ui/src/app/settings/page.tsx b/ui/src/app/settings/page.tsx index 3032215..84345d7 100644 --- a/ui/src/app/settings/page.tsx +++ b/ui/src/app/settings/page.tsx @@ -1,5 +1,7 @@ "use client"; +import { ExternalLink } from "lucide-react"; + import { MCPSection } from "@/components/MCPSection"; import { TelemetrySection } from "@/components/TelemetrySection"; import { @@ -26,7 +28,15 @@ export default function SettingsPage() { MCP Server Let AI agents access your Dograh workspace and documentation via - the Model Context Protocol. + the Model Context Protocol.{" "} + + Learn more + @@ -38,7 +48,15 @@ export default function SettingsPage() { Telemetry - Configure Langfuse tracing for your voice agent calls. + Configure Langfuse tracing for your voice agent calls.{" "} + + Learn more + diff --git a/ui/src/components/MCPSection.tsx b/ui/src/components/MCPSection.tsx index b89d2f6..6412641 100644 --- a/ui/src/components/MCPSection.tsx +++ b/ui/src/components/MCPSection.tsx @@ -13,25 +13,7 @@ export function MCPSection() { (typeof window !== "undefined" ? window.location.origin : ""); const endpoint = `${backendUrl}/api/v1/mcp/`; - const clientConfig = JSON.stringify( - { - mcpServers: { - dograh: { - url: endpoint, - headers: { "X-API-Key": "YOUR_API_KEY" }, - }, - }, - }, - null, - 2, - ); - - const claudeCliCommand = `claude mcp add --transport http dograh ${endpoint} \\ - --header "X-API-Key: YOUR_API_KEY"`; - const [endpointCopied, setEndpointCopied] = useState(false); - const [configCopied, setConfigCopied] = useState(false); - const [cliCopied, setCliCopied] = useState(false); const handleCopy = async ( value: string, @@ -47,8 +29,8 @@ export function MCPSection() {

- Connect an AI agent (Claude Desktop, Cursor, etc.) to this URL over - Streamable HTTP. Requires an API key in the X-API-Key header.{" "} + Connect an MCP-compatible AI assistant to this URL over Streamable + HTTP. Requires an API key in the X-API-Key header.{" "}

-
- -

- Run this in your terminal to register Dograh as an MCP server with - Claude Code. -

-
-
-            {claudeCliCommand}
-          
- -
-
- -
- -

- Paste this into your MCP client's config file (e.g. Claude - Desktop's{" "} - - claude_desktop_config.json - - ) and replace{" "} - - YOUR_API_KEY - - . -

-
-
-            {clientConfig}
-          
- -
-
+

+ For step-by-step setup with Claude Code, Claude Desktop, Cursor, and + other clients, see the{" "} + + MCP integration guide + + . +

); }