npx agentspec-cli install ae44fa58-044c-4012-9100-d1201368df38 --file-type cursor-rules→ .cursor/rules/
---
globs:
- mcp_server/**
---
## MCP Server Conventions
- Standalone process — **no imports** from `ada_backend/` or `engine/`.
- Tools are thin wrappers: validate inputs, call `DraftnrunClient` or `SupabaseClient`, format response. No business logic.
- Tool naming: `snake_case` verbs matching the API action (`list_`, `get_`, `create_`, `update_`, `delete_`).
- Auth: `SupabaseProvider` from FastMCP. Tokens are standard Supabase JWTs. MCP server does NOT issue its own tokens.
- Consent page: lives in `back-office/src/pages/oauth/callback.vue`, NOT in the MCP server. Supabase redirects to `SITE_URL + authorization_path` for consent.
- Use `get_access_token()` from `fastmcp.server.dependencies` to get the JWT; `.token` for the raw string, `.claims["sub"]` for user ID.
- Org context: session-scoped via Redis and keyed by the MCP session ID when available. Tools must check for active org before calling org-scoped endpoints (use `require_org_context`). Developer+ operations (create/update/delete/pause/resume cron, OAuth, `create_agent`, knowledge mutations, Typeform webhook setup, git sync configure/disconnect) use `require_role`. `trigger_cron` is org-scoped (member+).
- Workflow creation: `create_workflow` creates workflow-type projects. Agent projects use `create_agent`.
- Target-org permissions: tools that accept an explicit `org_id` must validate the caller's role on that target organization, not only on the active org session.
- Component search: `search_components(query)` must reject blank or whitespace-only queries instead of returning the full catalog.
- Error handling: never bare except. Map HTTP errors to descriptive MCP tool error messages via `ToolError`.
- Sentry: `MCPIntegration` is auto-configured. Use `sentry_sdk.logger` for structured logging.
- Response trimming: large payloads (>50KB) are truncated by `DraftnrunClient._trim_response`. Trimming is controllable per-tool via `ToolSpec.trim` (default `True`) and per-call via the `trim` parameter on all HTTP methods. `get_graph` and `list_components` are untrimmed.
- When adding/removing/renaming MCP tools: update `mcp_server/README.md`, the relevant `docs://` resource in `mcp_server/docs.py`, and this rule file in the same diff.
- When changing any MCP behavior, payload, auth, limitation, or guardrail: update the matching `docs://` resource in `mcp_server/docs.py` in the same diff.
- Example UUIDs in `docs.py` must come from code (`uuid.uuid4()`), stored as module constants / placeholders replaced at import — never hand-written hex in prose. See `_GRAPH_DOC_*` in `docs.py`.
- When changing file/document behavior: always update `docs://file-management` and `mcp_server/README.md` in the same diff.
- When adding a new tool domain: create a file in `mcp_server/tools/`, register in `mcp_server/tools/__init__.py`.
- Never reuse IDs, instance UUIDs, source IDs, or graph JSON from another project/org as a shortcut. Re-fetch current state with `get_graph`, `list_components`, `search_components`, `list_sources`, etc.
- Ask for explicit user permission before publish/delete/revoke OAuth or guiding OAuth setup in the web UI.
- Prefer dedicated components over `python_code_runner` / `terminal_command_runner`; keep code tools for small, bounded tasks.
- Prefer dedicated search components for web research when the catalog already provides them.
- Do not describe knowledge documents as original downloadable files or claim MCP has a generic file upload/download API unless that behavior actually exists.
- Factory spec validation at registration time catches unresolved path placeholders, `body_org_key` without org/role scope, and missing roles on role-scoped specs.
- Body fields with `None` values are omitted from the JSON payload (not serialized as JSON `null`).
- Redis fallback is recoverable: after a connection failure, the client retries automatically after 60 s.
- Treat `_truncated` responses as partial data, never as complete truth.
- `get_org_token_usage` reports monthly input/output tokens from stored trace spans only; `years`/`months` accept
lists or `"all"`, and per-model rows depend on persisted `model_id` values, not recomputation from prompts or
provider APIs.
- Tool port configurations: component instances in graph payloads include `port_configurations` (setup modes: `ai_filled`, `user_set`, `deactivated`) and a computed `tool_description`. `tool_description_override` customizes the description shown to the AI. When changing tool port behavior, update `docs://graphs`, `docs://agent-config`, and `mcp_server/README.md`.
- QA custom columns: entry `custom_columns` dicts are keyed by column UUID, not display name. Always use `list_custom_columns` to discover the mapping before writing. See `docs://qa` and `docs://known-quirks`.
- CSV tools: `export_dataset_csv` / `import_dataset_csv` handle dataset round-trips. The export builds CSV from paginated `list_entries` internally (no `graph_runner_id` needed). The import uses multipart file upload to the backend's CSV import endpoint.
- Client methods: `api.get_raw()` returns raw text (for non-JSON endpoints). `api.post_file()` handles multipart uploads. Both are available for custom tools that need non-JSON request/response patterns.
- Org selection must be sequential — parallel calls with `select_organization` race and fail. See `docs://known-quirks`.
- `update_graph` and `update_graph_topology_v2` tool descriptions warn callers to `get_guide('graphs')` first and to close the browser tab to avoid race conditions with the UI auto-save. `update_graph_topology_v2` additionally documents full-replace edge semantics.
- `configure_agent`, `add_tool_to_agent`, and `remove_tool_from_agent` are for AGENT-type projects only. For WORKFLOW-type projects, use `update_component_parameters` to change component parameters, or `get_graph` + `update_graph` for structural changes.
- Keep `get_project_overview` parity with API-level project settings exposed by `get_project`.
- AI Agent `skip_tools_with_missing_oauth` (default `True`): at agent startup, tools with `is_available()` False (e.g. missing OAuth) are excluded from the LLM tool registry. Documented in `docs://agent-config`, `docs://integrations`, and `mcp_server/README.md` guardrails; change via `configure_agent` or `update_component_parameters`.
- Neverdrop-branded Google integration components use distinct OAuth provider filters: `google-mail-neverdrop` and `google-calendar-neverdrop`. Always discover the component via `search_components()` and verify matching OAuth connections with `list_oauth_connections(provider_config_key)` before graph edits.
- `update_component_parameters` performs a read-modify-write on a single component's parameters. It GETs the full graph to locate the component, then PUTs only the target component via the V2 single-component endpoint (`/v2/.../components/{instance_id}`), avoiding the V1 full-graph hash-based skip. Preferred over `update_graph` for single-parameter changes on workflow components. Avoid modifying `drives_output_schema` fields (`payload_schema`, `output_format`) unless intending to change dynamic output ports. Internally filters out INPUT-kind parameters and converts read-format `field_expressions` to write-format `input_port_instances` before PUT to prevent lossy round-trips (e.g. `json_build` expressions whose `value` is the non-invertible placeholder `[JSON_BUILD]`). Raises `ToolError` if the caller tries to set a literal value on a parameter wired with a non-literal field expression (`ref` or `json_build`); use `update_component_v2` to rewire those parameters.
- Run retries are run-scoped via `retry_run(project_id, run_id, env=None)`. The backend reuses the original run's `graph_runner_id` and persisted `run_inputs`. The optional `env` is a legacy fallback only needed when both `graph_runner_id` and `env` are null on the original run; do not reintroduce project-scoped retry policy fields.
- `update_graph` supports optional optimistic locking: pass `last_edited_time` from a previous response to detect concurrent edits (409 Conflict).
- File-based graph v2 tools: granular tools (`create_component_v2`, `update_component_v2`, `delete_component_v2`, `update_graph_topology_v2`) for front/MCP. Git sync uses the same service functions internally (no MCP tool). Granular flow: create component → update topology to connect it. Field expression refs in `input_port_instances` support `file_key` (e.g. `{"type": "ref", "file_key": "start", "port": "output"}`) as an alternative to `instance` UUID; the v2 mapper resolves `file_key` → UUID before saving. `update_component_v2` uses full-replace semantics for `parameters` and `input_port_instances` — callers must include ALL parameters from the graph, not only the ones being changed. For single-parameter changes prefer `update_component_parameters`.
- Edge `origin`/`destination` accept both plain UUID strings and dicts like `{"instance_id": "uuid"}` — the backend normalizes.
- JSON-typed parameters (e.g. If/Else `conditions`) accept both native lists and JSON-encoded strings — the backend normalizes lists via `parse_expression_flexible`.
- If/Else branch edges use `order: 0` for true and `order: 1` for false/else. Set `enable_false_path=true` on the component before wiring `order: 1`; when it is false, false conditions select no downstream branch.
MCP Server Development Rules
This file contains rules and guidelines for developing MCP (Model Context Protocol) servers using fast-mcp and TypeScript, specifically for integrating with Sunra.ai services.
by AgentHub Crawler
mcp-builder
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
by AgentHub Crawler
rules
Windsurf IDE rules and conventions for AI-assisted development.
by AgentHub Crawler
Sign in to leave a comment.
Development rules
├── cli/ # Command-line interfaces ├── controllers/ # Business logic ├── resources/ # MCP resources: expose data and content from your servers to LLMs ├── services/ # External API interactions
by AgentHub Crawler