# @aigentyc/mcp > Model Context Protocol server for the Aigentyc platform. Lets Claude Code, Cursor, Windsurf, Claude Desktop, and any MCP-compatible agent drive an Aigentyc project end-to-end: add documents, configure the chat agent, build custom tools — and scaffold or embed the front-end chat widget (`@aigentyc/chat-sdk`) — all from one conversation. The output is a working chat experience on the user's site. ## Zero-to-chat in one conversation ``` You: "Add my docs/ folder, set the system prompt to be terse and helpful, and scaffold a Next.js chat app at ./my-app." Claude: aigentyc_get_started → "kb empty, no system prompt" files_upload({ paths: [...] }) → 14 docs ingested config_update({ patch: { systemPrompt: "..." } }) aigentyc_get_started → "snippetReady: true" chat_widget_scaffold({ destination: "./my-app", template: "next" }) → ✓ done. cd my-app && npm install && npm run dev ``` ## End-to-end recipe 1. **Discover state** — `aigentyc_get_started` returns project status + prioritised `nextSteps`. Always call this first in a new conversation. 2. **Add content** — pick the right ingest tool: `files_upload` (local files), `documents_create_from_text` (raw text), `extract_from_urls` (batch URLs), `link_sources_create` (crawl a website). 3. **Tune the chat** — `config_update` for the system prompt + chat model, `personas_upsert` for audience-specific tone, `tools_create` for custom REST/JS actions exposed to chat. 4. **Embed** — three options: - **`chat_widget_setup`** — confirms readiness, returns paste-ready snippet + install commands. Use when user has an app already. - **`chat_widget_scaffold`** — runs `npm create aigentyc-chat@latest ` to bootstrap a fresh Vite or Next.js starter wired to the project. For greenfield apps. - **`chat_widget_get_snippet`** — just the snippet, no readiness check. For when you've already verified setup. ## Install ```bash npx @aigentyc/mcp login \ --api-key tyco_pk_XXXX \ --project-id proj_XXXX ``` `login` verifies the key against `/api/auth/api-keys/verify` and writes `~/.aigentyc/config.json` with `0600` perms. The server refuses to start if perms are wider. **Dev-only flag**: pass `--allow-insecure` to permit plaintext HTTP against non-loopback hosts. Never use this against production. ## Wire into your agent ### Claude Desktop / Claude Code `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS): ```json { "mcpServers": { "aigentyc": { "command": "npx", "args": ["-y", "@aigentyc/mcp"] } } } ``` ### Cursor Settings → MCP → add server: ```json { "aigentyc": { "command": "npx", "args": ["-y", "@aigentyc/mcp"] } } ``` Restart the client. The new tools appear under the `aigentyc` namespace. ## Commands ``` aigentyc-mcp serve Start the stdio MCP server (default) aigentyc-mcp login Save + verify an API key profile aigentyc-mcp logout Remove a profile aigentyc-mcp doctor Verify config + transport + clock skew + reachability ``` ## Tools (86 total, 20 domains) - **embed (E2E entry points)** — aigentyc_get_started, chat_widget_setup, chat_widget_get_snippet, chat_widget_scaffold - **documents** — list, get, delete, create_from_text, merge, versions - **files** — list, get, upload (path-based), delete, reprocess, versions, bulk_audience - **extract** — from_urls (jobified for api-key) - **link_sources** — list, get, create, update, delete, list_items, update_item, delete_item - **page_questions** — list, set_manual, auto_generate (jobified), delete_page - **data_stores** — full CRUD + bulk_upsert + import + export + scan_website (jobified) - **tools** (custom-tool CRUD) — list, get, create, update, delete, execute_dry_run - **flows** — list, get, create, update, delete - **golden_answers** — list, create, update, delete + ai_improve + ai_generate_variations - **corrections** — list, create, update_status - **personas** — list, upsert, delete - **config** — get (secrets redacted for api-key), update (secret writes rejected) - **backups** — list, create (jobified), restore (jobified), download, import, delete - **analytics** — overview, sessions, session_timeline, comments - **branches** — list - **search** — kb_search (read-only authoring aid) - **jobs** — status, list, wait ## Async job pattern Long-running ops (backup create/restore, extract, data-store scan, page-questions auto-generate) return `{ jobId, status: "queued" }`. Poll with `jobs_wait`: ``` extract_from_urls({ urls: [...] }) → { jobId: "abc-123", status: "queued" } jobs_wait({ jobId: "abc-123" }) → blocks until terminal; returns { status: "completed", result: {...} } ``` Concurrency cap: 3 active jobs per project. ## Security - **Project-scoped keys**: a key for project A cannot read/write project B (403). - **Per-key rate limits**: 300 reads/min, 60 writes/min. 429 with `Retry-After` over the limit. - **Secrets**: `config.get` redacts `openaiApiKey` + `customHttpHeaders` to `***` for api-key callers. `config.update` rejects writes to those fields with 403. Backup downloads (single + ZIP) deep-redact secrets. - **Custom tool code**: `tools.create` rejects `transformCode` / `executeCode` containing `process.env`. Use `apiConfig.headers` with template placeholders for secrets. - **Destructive ops** (`*.delete`, `backups.restore`): require `confirm: true`. - **Path uploads**: `files.upload` refuses paths outside `$CWD` / `$HOME`, refuses non-regular files, caps 50MB/file, 500MB/batch. - **URL inputs**: `extract.from_urls` + `link_sources.create` reject RFC1918 / loopback / cloud-metadata hosts. - **Audit log**: every api-key request is logged server-side (`api_key_audit_log` table) with `keyId`, `projectId`, `route`, `method`, `status`, `latencyMs`, `requestId`. Reads sampled at 10%; writes 100%. ## Recipes ### Vibe-coder one-shot — docs to embedded chat in 60 seconds ``` 1. aigentyc_get_started() 2. files_upload({ paths: ["docs/**/*.md"], indexAsDocuments: true }) 3. config_update({ patch: { systemPrompt: "You are the support agent for ACME. Cite sources from docs." } }) 4. chat_widget_scaffold({ destination: "./acme-chat", template: "next", confirm: true }) 5. → cd acme-chat && npm install && npm run dev ``` ### Add a markdown KB from local files ``` files_upload({ paths: ["docs/intro.md", "docs/api.md"], indexAsDocuments: true }) ``` The MCP reads each file (text formats only — `.md`, `.txt`, `.json`, `.csv`, `.html`, …), uploads metadata to `uploaded_files`, then chunks + embeds + indexes via `documents/create`. After ingest, `chat_widget_setup` returns paste-ready snippet. ### Crawl a website + dedupe before adding more docs ``` 1. link_sources_create({ sourceUrl: "https://example.com", sourceType: "website" }) 2. jobs_wait({ jobId: ... }) — wait for crawl to finish 3. search_kb_search({ query: "billing FAQ" }) // confirm it indexed ``` ### Build a custom tool end-to-end ``` 1. tools_create({ name: "submitForm", toolType: "rest_api", apiConfig: { method: "POST", url: "...", body: "name={{name}}" }, inputSchema: [{ name: "name", type: "string", required: true }], }) 2. tools_execute_dry_run({ toolId, input: { name: "Test" } }) // verify output before exposing to chat ``` ### Update system prompt ``` config_update({ patch: { systemPrompt: "You are the support agent for ACME..." } }) ``` (Cannot update `openaiApiKey` over api-key — use the dashboard for secrets.) ## Troubleshooting - **404 on login** — auth-service may be on a different origin in dev. `login` falls back to dashboard ping. Use `--base-url http://localhost:3000` for local Docker. - **Tool calls hang** — confirm `aigentyc-mcp doctor` passes. Most failures are wrong base-url, expired key, or clock skew (>60s breaks auth). - **Tool created but UI doesn't show it** — fully restart Claude Desktop / Cursor. Server-side caches invalidate on every write; client-side router caches don't. - **Empty fields on tool call** — required string fields with `min(1)` get rejected by Zod, prompting the LLM to gather real values from the user. If a tool fires with empty inputs, the field wasn't marked required at creation. ## Versioning Server (`@aigentyc/mcp` on npm) and platform (`app.aigentyc.com`) version independently. The platform maintains backward compatibility with older MCP releases — endpoints aren't broken without deprecation.