{
  "$schema": "https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",
  "version": "1.0",
  "protocolVersions": [
    "2025-11-25",
    "2026-07-28"
  ],
  "serverInfo": {
    "name": "needle",
    "title": "Needle",
    "version": "1.1.0",
    "vendor": "Needle",
    "homepage": "https://useneedle.net",
    "documentation": "https://useneedle.net/docs/mcp",
    "description": "Find people asking for your product on Reddit, Hacker News, Stack Overflow, GitHub, Bluesky and other communities; triage the leads and draft replies you post yourself. Needs a Needle account on the Growth or Scale plan.",
    "icon": "https://useneedle.net/logo-light-512w.svg",
    "registryName": "net.useneedle/needle"
  },
  "transport": {
    "type": "streamable-http",
    "endpoint": "https://api.useneedle.net/mcp"
  },
  "authentication": {
    "required": true,
    "schemes": [
      {
        "type": "oauth2",
        "description": "Sign in with a Needle account. OAuth 2.1 with PKCE (S256); discovery starts from the 401 on /mcp.",
        "protectedResourceMetadata": "https://api.useneedle.net/.well-known/oauth-protected-resource/mcp",
        "authorizationServerMetadata": "https://api.useneedle.net/.well-known/oauth-authorization-server",
        "scopes": [
          "leads:read",
          "leads:write",
          "search:run",
          "drafts:write",
          "trending:read",
          "offline_access"
        ]
      },
      {
        "type": "bearer",
        "description": "API key from Settings → API & MCP, sent as Authorization: Bearer ndl_live_…",
        "scopes": [
          "leads:read",
          "leads:write",
          "search:run",
          "drafts:write",
          "trending:read"
        ]
      }
    ],
    "instructions": "https://useneedle.net/auth.md"
  },
  "capabilities": {
    "tools": {
      "listChanged": false
    }
  },
  "tools": [
    {
      "name": "list_brands",
      "title": "List brands",
      "description": "List the brands (products) this Needle account monitors, with their keywords, networks and monitoring schedule.",
      "scope": "leads:read",
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "get_leads",
      "title": "Get leads",
      "description": "Use get_leads to answer 'who should I reply to today?'. Returns saved leads (social posts from people who may need the user's product), newest first.",
      "scope": "leads:read",
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "get_lead",
      "title": "Get one lead",
      "description": "Get one lead with its full post text (up to 4,000 characters), tier, intent and the evidence sentence.",
      "scope": "leads:read",
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "update_lead_status",
      "title": "Update lead status",
      "description": "Set the triage status of up to 100 leads: 'inbox', 'replied', 'done' or 'dismissed'.",
      "scope": "leads:write",
      "annotations": {
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "search",
      "title": "Search communities",
      "description": "Run a live search for 1-5 keywords across community networks (Reddit, Hacker News, forums and more) and return the best leads found, at most 10 per network and 40 in total.",
      "scope": "search:run",
      "annotations": {
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": true
      }
    },
    {
      "name": "get_search",
      "title": "Get search results",
      "description": "Get the status and leads of a search started with search. Free: does not count against the monthly call quota.",
      "scope": "search:run",
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "draft_reply",
      "title": "Draft a reply",
      "description": "Write two reply drafts (best and alternate) for one lead, in the user's brand voice. Needle never posts: the drafts are text for the user to review and post themselves.",
      "scope": "drafts:write",
      "annotations": {
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false
      }
    },
    {
      "name": "get_trending_problems",
      "title": "Get trending problems",
      "description": "List problems people are currently discussing across communities, ranked by how much they are trending. Not specific to the user's brands.",
      "scope": "trending:read",
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "get_usage",
      "title": "Get usage",
      "description": "Show the user's plan, API calls left this month, and searches and reply drafts left today, with reset times (UTC). Free: does not count against the quota.",
      "scope": null,
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    }
  ],
  "relatedApis": {
    "rest": "https://api.useneedle.net/v1",
    "openapi": "https://api.useneedle.net/v1/openapi.json",
    "documentation": "https://useneedle.net/docs/api"
  }
}
