ReferenceMCP server reference

Selda MCP Server

The Selda MCP server lets external AI tools (Claude Desktop, Claude Code, ChatGPT, or any Model Context Protocol client) drive a user’s Selda workspace: list projects, inspect leads and campaigns, read threads, and run the GTM pipeline. It is a paid/Scale-tier feature, gated behind an API key.

The Selda web app is at https://app.selda.ai.


Two parts

There are two distinct pieces:

  1. The Node MCP server, mcp-server/index.ts. A small stdio MCP server that exposes the Selda tools to the AI client and forwards each call over HTTP to the Convex backend. Runs locally (e.g. spawned by Claude Desktop via npx tsx).

  2. The Convex HTTP endpoints it calls, defined in convex/mcpApi.ts and routed in convex/http.ts:

    EndpointMethodPurpose
    /mcp/queryPOSTRead operations (queries)
    /mcp/mutatePOSTWrite operations (mutations)
    /mcp/runPOSTActions (pipeline / engine)

    Each also has an OPTIONS route for CORS preflight. The base URL is the deployment’s .convex.site host (prod default: https://brave-buzzard-349.eu-west-1.convex.site, overridable via SELDA_API_URL / VITE_CONVEX_SITE_URL).

    The HTTP body is always { fn, args }, where fn is a registry key (e.g. projects.list) and the handler returns { value } on success or { error } with a non-200 status on failure.


Authentication & scoping

  • API key format: sk_live_… (prefix + 40 random alphanumeric chars).
  • Transport: sent as a Bearer token: Authorization: Bearer sk_live_…. The Node server reads it from the SELDA_API_KEY env var.
  • Creation: keys are minted via apiKeys.createKey (called from the app UI: Settings → Apps → API Key). The full plaintext key is returned once at creation and never stored or shown again.
  • Storage: only a SHA-256 hash of the key (keyHash) plus a display keyPrefix (first 16 chars + ...) are persisted in the apiKeys table. The plaintext key is never written to the database.
  • Validation: every HTTP call runs apiKeys.validateKey over the request’s hashed token. A key is rejected if it is missing/expired, revoked (revokedAt), the owning user is deleted/disabled, or the owning org no longer exists. On success it returns the key’s orgId, userId, and scopes.
  • Revocation: apiKeys.revokeKey (UI) sets revokedAt; the key stops validating immediately.

Scopes

ScopeGrantsSelf-grantable
read/mcp/query (and required by all read calls)Yes
write/mcp/mutateYes
pipeline/mcp/run (engine / pipeline actions)Yes
admincross-org admin queries (all users/orgs/projects/stats)No

Default scopes for a newly created key are ["read", "write", "pipeline"]. The admin scope exists for internal cross-org tooling and is not granted through normal self-service key creation (security-hardened, see the internal security notes).

Org isolation

Each HTTP handler:

  1. checks the required scope for that endpoint (e.g. /mcp/query requires read), returning 403 if missing;
  2. injects the key’s orgId (and, where relevant, userId) server-side into the called function’s args.

Because the org id comes from the validated key, never from the request body, a key can only ever reach data belonging to its own organization. Every underlying mcpQueries.* function re-verifies org ownership (e.g. a lead is only returned if its project’s orgId matches the key’s org). One org’s key cannot read or mutate another org’s projects, leads, campaigns, or messages.


Tools

The Node server exposes 13 tools (TOOLS in mcp-server/index.ts). Each maps to one or more { fn, args } calls against the Convex HTTP API.

ToolPurposeKey args
selda_list_projectsList your Selda projects (name, website, status, id). Returns the projectId needed by other tools.none
selda_get_projectProject detail: business context, market analysis, ICP, settings.projectId
selda_list_leadsList leads for a project (contact, company, fit score, status).projectId, limit? (default 50)
selda_get_leadFull lead detail: contact, company research, fit, why-good-lead, outreach angle, notes.leadId
selda_update_leadUpdate a lead’s status (newcontactedrespondedqualified/unqualified) and/or notes.leadId, status?, notes?
selda_list_campaignsList a project’s campaigns (status, type, channels).projectId
selda_get_campaignCampaign detail: status, channels, stats, settings, lead count.campaignId
selda_campaign_statsCampaign performance: sent / delivered / opened / clicked / replied / bounced.campaignId
selda_list_messagesList sent/received messages for a project (direction, recipient, subject, status).projectId
selda_get_threadFull email thread with one lead, all sent and received messages.leadId
selda_run_pipelineRun the full GTM pipeline: find leads → research → write personalized messages. The core engine.projectId, idea, targetLeadCount? (default 5)
selda_lookupGeneral Selda lookup verb (resolve/inspect an entity from a reference).reference / query args
selda_creditsCheck credit balance: daily free credits, lead credits, usage, plan.none

The live MCP server may also expose an selda_add_lead tool for adding known contacts directly (backed by the leads.add mutation in convex/mcpQueries.ts).

Usage guidance (from the MCP server instructions)

  • The app is at https://app.selda.ai, never use selda.city or other domains.
  • Always call selda_list_projects first to obtain a projectId before any other operation.
  • When a user shares a URL or webpage with specific companies/people, add them directly (e.g. selda_add_lead), do not pass URLs to selda_run_pipeline.
  • Use selda_run_pipeline only for open-ended searches like “find SaaS founders in Finland”.
  • selda_run_pipeline runs the engine and costs credits; results (leads + drafted messages) appear after a few minutes, poll with selda_list_leads.

Connecting a client

  1. In the Selda app go to Settings → Apps → API Key and create a key. Copy the sk_live_… value (shown once).

  2. Point your MCP client at the Node server, passing the key as SELDA_API_KEY. Example Claude Desktop config:

    {
      "mcpServers": {
        "selda": {
          "command": "npx",
          "args": ["tsx", "/path/to/mcp-server/index.ts"],
          "env": { "SELDA_API_KEY": "sk_live_..." }
        }
      }
    }

    Or run the guided setup: npx tsx mcp-server/setup.ts.

  3. Every call is automatically scoped to the org that owns the key. Pipeline runs consume credits, so check selda_credits if runs start failing.


Source files

FileRole
mcp-server/index.tsNode stdio MCP server, tool definitions, HTTP client
mcp-server/handlers.tsExtra tool handlers (analysis, discussions, channels, drafts)
mcp-server/setup.tsInteractive client configuration
convex/mcpApi.tsHTTP handlers for /mcp/query, /mcp/mutate, /mcp/run; auth + scope + org injection
convex/mcpQueries.tsOrg-scoped internal queries/mutations/actions the HTTP layer calls
convex/apiKeys.tsAPI key creation, validation, revocation (SHA-256 hashed storage)
convex/http.tsRoutes the MCP endpoints