{
  "markdown": "# @neuronsearchlab/mcp\n\nMCP (Model Context Protocol) server for [NeuronSearchLab](https://www.neuronsearchlab.com). Gives any MCP-compatible AI client (Claude, Codex, Cursor, Windsurf, etc.) direct access to NeuronSearchLab recommendations, product/content search, catalogue operations, analytics, and platform controls.\n\n```\n\"Get 5 recommendations for user alice@example.com\"\n\"Check my current plan and show which resources are over their limits\"\n\"Create a new context called Twitter Feed\"\n\"Add a pin rule so Nike items always appear in the top 3\"\n\"Why did item prod-456 rank first for bob?\"\n```\n\nTwo ways to run it:\n\n- **Hosted (recommended, no install):** `https://console.neuronsearchlab.com/api/mcp` — Streamable HTTP with OAuth sign-in or an NSL API key. Listed on the [MCP Registry](https://registry.modelcontextprotocol.io) as `com.neuronsearchlab/mcp` (search `neuronsearchlab` in the registry API or directory).\n- **Local stdio via npm:** `npx -y @neuronsearchlab/mcp` in two modes — `public` (recommendations, events, catalogue via OAuth client credentials) or `internal` (admin platform via console API key).\n\n---\n\n## Connect to the hosted server (no install)\n\nThe hosted endpoint runs a submission-safe customer administration profile. It includes first-class tools for plan and usage visibility, ranking configuration, experiments, training, analytics, catalogue inspection, API-key inventory and revocation, integrations, and event types. Every hosted tool declares its OAuth requirement and requires the authenticated team's `admin` scope. Credential creation, billing mutations, and the arbitrary platform API fallback remain available only to trusted local/internal clients so secrets, purchases, and unbounded API calls are not exposed in ChatGPT. Keys minted through OAuth consent appear in [console → Security](https://console.neuronsearchlab.com/security) and can be revoked there anytime.\n\n**claude.ai / Claude Desktop** — Settings → Connectors → Add custom connector → paste `https://console.neuronsearchlab.com/api/mcp` → **Connect**, then sign in to your NeuronSearchLab console and approve the scopes.\n\n**Claude Code**\n\n```bash\n# OAuth (browser sign-in):\nclaude mcp add --transport http neuronsearchlab https://console.neuronsearchlab.com/api/mcp\n# …or with an API key:\nclaude mcp add --transport http neuronsearchlab https://console.neuronsearchlab.com/api/mcp \\\n  --header \"Authorization: Bearer nsl_your_key\"\n```\n\n**OpenAI Codex** — in `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.neuronsearchlab]\nurl = \"https://console.neuronsearchlab.com/api/mcp\"\nbearer_token_env_var = \"NSL_API_KEY\"\n```\n\n**Cursor / Windsurf / other Streamable HTTP clients**\n\n```json\n{\n  \"mcpServers\": {\n    \"neuronsearchlab\": {\n      \"url\": \"https://console.neuronsearchlab.com/api/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer nsl_your_key\" }\n    }\n  }\n}\n```\n\n---\n\n## Resources\n\n- Product site: https://www.neuronsearchlab.com\n- MCP setup guide: https://docs.neuronsearchlab.com/sdk/mcp\n- AI agents for recommendation operations: https://www.neuronsearchlab.com/blog/ai-agents-for-recommendation-operations\n- Recommendation systems reading path: https://www.neuronsearchlab.com/blog/recommendation-systems\n\n## Tools\n\n### API tools\n\n| Tool | Description |\n|------|-------------|\n| `get_recommendations` | Fetch personalised recommendations for a user |\n| `get_auto_recommendations` | Auto-sectioned feed with pagination (infinite scroll) |\n| `track_event` | Record a user interaction (click, view, purchase, etc.) |\n| `upsert_item` | Add or update a catalogue item |\n| `patch_item` | Partially update an item (enable/disable, change fields) |\n| `delete_items` | Permanently remove items from the catalogue |\n| `search_items` | Search the catalogue by keyword |\n| `explain_ranking` | Explain why an item ranked where it did for a user |\n\n## Modes\n\n### Public mode\n\nUses OAuth client credentials and the public API.\n\nSupported:\n- recommendations\n- events\n- catalogue operations\n\n### Internal mode\n\nUses a NeuronSearchLab API key with the `admin` scope against the console API.\n\nCurrently supported:\n- account plan and limits: `get_account_plan` returns the effective plan, resolved limits, current usage, and exact overages\n- catalogue search and ranking debug: `search_items`, `explain_ranking`\n- contexts: `list_contexts`, `create_context`, `update_context`, `delete_context`, `get_context`\n- pipelines: `list_pipelines`, `create_pipeline`, `update_pipeline`, `delete_pipeline`, `activate_pipeline`, `deactivate_pipeline`, `clone_pipeline`, `get_pipeline`\n- rules: `list_rules`, `create_rule`, `update_rule`, `delete_rule`, `toggle_rule`, `enable_rule`, `disable_rule`, `get_rule`\n- segments: `list_segments`, `get_segment`, `create_segment`, `update_segment`, `delete_segment`\n- experiments: `list_experiments`, `get_experiment`, `create_experiment`, `update_experiment`, `start_experiment`, `stop_experiment`, `get_experiment_results`, `refresh_experiment_results`\n- training: `list_training_jobs`, `get_training_job`, `create_training_job`, `cancel_training_job`\n- analytics: `get_ranking_metrics`, `get_user_analytics`, `get_item_analytics`, `compare_items`, `top_items`\n- event types: `list_event_types`, `create_event_type`, `update_event_type`, `delete_event_type`\n- credentials and integrations: `list_api_keys`, `revoke_api_key`, `list_integrations` (`create_api_key` is local/internal only because it returns credential material)\n- fallback UI coverage for trusted local/internal clients only: `list_platform_routes`, `call_platform_api`\n\n---\n\n## Quickstart (local stdio)\n\n### 1. Get credentials\n\nGenerate **SDK Credentials** (OAuth 2.0 client ID + secret) from the [NeuronSearchLab console](https://console.neuronsearchlab.com/security).\n\n### 2. Add to Claude Desktop\n\n**Public mode** (recommendations, events, catalogue):\n\nEdit `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"neuronsearchlab\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@neuronsearchlab/mcp\"],\n      \"env\": {\n        \"NSL_CLIENT_ID\": \"your-client-id\",\n        \"NSL_CLIENT_SECRET\": \"your-client-secret\"\n      }\n    }\n  }\n}\n```\n\n**Internal mode** (admin platform — contexts, pipelines, rules, analytics, etc.):\n\n```json\n{\n  \"mcpServers\": {\n    \"neuronsearchlab\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@neuronsearchlab/mcp\"],\n      \"env\": {\n        \"NSL_PLATFORM_MODE\": \"internal\",\n        \"NSL_API_KEY\": \"your-admin-api-key\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop. You'll see a 🔌 **neuronsearchlab** indicator in the toolbar when it's connected.\n\n### Try it: recommendation-ops demo\n\nOnce connected, run this named demo path before wiring the server into a larger workflow. It proves that an AI client can operate the recommender as an investigation surface rather than just call a recommendation endpoint.\n\n1. **List contexts** so the assistant confirms the exact surface it is about to inspect.\n2. **Fetch recommendations** for a known test user and context.\n3. **Search the catalogue** for a concrete product/content phrase and compare the returned item IDs with the recommendation set.\n4. **Explain one ranked item** using the `request_id` from the recommendation or search response when available.\n5. **Optional, sandbox only:** draft or toggle a rule after the explanation shows the expected leak. Keep production contexts read-only unless the operator explicitly approves a write.\n\n```text\nUse the NeuronSearchLab MCP server in read-only mode first.\nList my recommendation contexts and choose the homepage-feed context.\nGet 10 recommendations for user demo-user@example.com using context homepage-feed.\nSearch the catalogue for waterproof jackets and show the top 5 item ids.\nExplain why the first recommended item ranked first, using the request_id from the recommendation response if available.\nIf you see a relevance leak, draft the smallest rule that would fix it, but do not create or toggle the rule yet.\n```\n\nInternal/admin mode can also inspect operational state before making changes:\n\n```text\nList ranking rules for the homepage-feed context.\nShow the latest ranking metrics for that context.\nCompare item jacket-123 with item jacket-456 and explain which rule or signal separates them.\n```\n\nNext steps after the smoke test:\n\n- create a scoped API key for the client or MCP server\n- connect one real recommendation context, such as `homepage-feed`\n- add request attribution to click/view events before judging ranking quality\n\n### 3. Cursor / other MCP clients\n\nFollow your client's MCP server guide. The command is:\n\n```\nnpx @neuronsearchlab/mcp\n```\n\nSet `NSL_CLIENT_ID` + `NSL_CLIENT_SECRET` for public mode, or `NSL_PLATFORM_MODE=internal` + `NSL_API_KEY` for internal mode.\n\n---\n\n## Releases\n\nThis repo uses Changesets plus GitHub Actions for automated versioning and npm publishing.\n\n- Add a changeset for any user-facing package change with `npm run changeset`\n- Merge that PR into `main`\n- The `release.yml` workflow opens or updates a version PR\n- Merging the version PR publishes `@neuronsearchlab/mcp` to npm automatically\n\nTo enable trusted publishing, configure the package on npmjs.com to trust the `release.yml` workflow in this repository.\n\n---\n\n## Configuration\n\nAll configuration is via environment variables:\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `NSL_PLATFORM_MODE` | No | `public` | `public` or `internal` |\n| `NSL_CLIENT_ID` | Public mode | — | OAuth client ID from the console |\n| `NSL_CLIENT_SECRET` | Public mode | — | OAuth client secret from the console |\n| `NSL_API_KEY` | Internal mode | — | API key with `admin` scope |\n| `NSL_TOKEN_URL` | No | `https://auth.neuronsearchlab.com/oauth2/token` | Token endpoint |\n| `NSL_API_BASE_URL` | No | `https://api.neuronsearchlab.com` in public mode, `https://console.neuronsearchlab.com` in internal mode | API base URL |\n| `NSL_TIMEOUT_MS` | No | `15000` | Request timeout in milliseconds |\n\n---\n\n## Tool reference\n\n### `get_recommendations`\n\nFetch personalised recommendations for a user. Returns ranked items with scores and a `request_id` for attribution.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `user_id` | string | Yes | User identifier (UUID, email, or any stable string) |\n| `context_id` | positive integer | No | Context ID generated when the context is created in the console |\n| `limit` | integer 1–200 | No | Number of items to return (defaults to context value, usually 20) |\n| `surface` | string | No | Rerank surface override (e.g. `\"homepage\"`, `\"sidebar\"`) |\n\n**Example**\n```\nGet 10 recommendations for user alice@example.com using context 101\n```\n\n---\n\n### `get_auto_recommendations`\n\nFetch the next auto-generated section for a user's feed. Designed for infinite-scroll — each call returns one curated section (e.g. *\"Trending this week\"*, *\"New for you\"*) plus a cursor for the next section. Call until `done: true`.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `user_id` | string | Yes | User identifier |\n| `context_id` | positive integer | No | Optional console-generated context ID |\n| `limit` | integer 1–200 | No | Items per section |\n| `cursor` | string | No | Pagination cursor from the previous response |\n| `window_days` | integer | No | Days to look back for \"new\" content |\n\n---\n\n### `track_event`\n\nRecord a user interaction. Always pass `request_id` from the recommendations response to enable click-through attribution.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `event_id` | integer | Yes | Numeric event type ID from the admin console |\n| `user_id` | string | Yes | User who triggered the event |\n| `item_id` | positive integer | Yes | NSL-generated item ID returned by ingestion |\n| `request_id` | string | No | `request_id` from the recommendations response (for attribution) |\n| `session_id` | string | No | Session identifier for grouping events within a visit |\n\n---\n\n### `upsert_item`\n\nAdd or update an item in the catalogue. The `description` field is used to generate the embedding — write it to be rich and descriptive.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `name` | string | Yes | Display name |\n| `description` | string | Yes | Rich description for embedding generation |\n| `metadata` | object | No | Arbitrary key-value pairs returned with recommendations |\n\nThe item ID is generated by NSL and returned in the ingestion response; callers cannot supply it.\n\n---\n\n### `patch_item`\n\nPartially update an existing catalogue item.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `item_id` | positive integer | Yes | NSL-generated item ID to update |\n| `active` | boolean | No | `false` to exclude from recommendations without deleting |\n\n---\n\n### `delete_items`\n\nPermanently remove items. **Cannot be undone.** To temporarily exclude, use `patch_item` with `active: false`.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `item_ids` | positive integer[] (max 100) | Yes | NSL-generated item IDs to delete |\n\n---\n\n### `search_items`\n\nSearch the catalogue by keyword.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `query` | string | Yes | Text to search for |\n| `limit` | integer 1–100 | No | Max results (default 20) |\n\n---\n\n### `explain_ranking`\n\nExplain why a specific item was ranked at a given position for a user. Returns score breakdown, applied rules, and pipeline trace.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `item_id` | positive integer | Yes | NSL-generated item ID to explain |\n| `user_id` | string | No | User to score against (omit for neutral baseline) |\n| `context_id` | positive integer | No | Console-generated context ID to apply scoring rules from |\n\n---\n\n### `list_contexts`\n\nList all recommendation contexts (feeds) configured for your team.\n\n**Inputs** — none\n\n---\n\n### `create_context`\n\nCreate a new recommendation context.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `context_name` | string | Yes | Display name (e.g. \"Twitter Feed\") |\n| `context_key` | string | No | URL-safe key (auto-derived from name) |\n| `context_type` | enum | No | `homepage_feed`, `you_may_also_like`, `item_detail_related`, `search_assist`, `campaign_merchandising`. Default: `homepage_feed` |\n| `description` | string | No | Optional description |\n| `recommendation_type` | enum | No | `item_to_item`, `item_to_user`, `user_to_item`, `user_to_user`. Default: `user_to_item` |\n\n**Example**\n```\nCreate a new context called \"Twitter Feed\" with type homepage_feed\n```\n\n---\n\n### `update_context`\n\nUpdate an existing context.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `context_id` | integer | Yes | The context ID to update |\n| `context_name` | string | No | New display name |\n| `context_type` | enum | No | New context type |\n| `description` | string | No | New description |\n| `recommendation_type` | enum | No | New recommendation type |\n\n---\n\n### `delete_context`\n\nPermanently delete a context and its attached pipelines, rules, and feed blueprints.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `context_id` | integer | Yes | The context ID to delete |\n\n---\n\n### `list_pipelines`\n\nList all ranking pipelines.\n\n**Inputs** — none\n\n---\n\n### `create_pipeline`\n\nCreate a new ranking pipeline with default stages.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `name` | string | Yes | Pipeline name |\n| `description` | string | No | Optional description |\n| `context_id` | integer | No | Context to attach this pipeline to |\n| `is_active` | boolean | No | Default: `true` |\n\n---\n\n### `update_pipeline` / `delete_pipeline`\n\nUpdate or delete a pipeline by `pipeline_id`.\n\n---\n\n### `list_rules`\n\nList ranking rules, optionally filtered by `context_id`.\n\n---\n\n### `create_rule`\n\nCreate a ranking rule. Rule types:\n\n| Type | Effect |\n|------|--------|\n| `boost` | Increase matching items' scores (use `weight` 1.0–5.0) |\n| `bury` | Decrease matching items' scores (use `weight` 0.0–1.0) |\n| `pin` | Fix matching items at a specific position (use `pin_position`) |\n| `filter` | Remove matching items from results |\n| `cap` | Limit matching items to a fraction of results (use `cap_fraction`) |\n| `diversity` | Spread items across a field's values (use `diversity_field`, `diversity_max`) |\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `name` | string | Yes | Rule display name |\n| `rule_type` | enum | Yes | `boost`, `bury`, `pin`, `filter`, `cap`, `diversity` |\n| `conditions` | array | Yes | `[{ field, operator, value }]` — items must match all conditions |\n| `actions` | object | Yes | `{ type, weight?, pin_position?, cap_fraction?, ... }` |\n| `context_id` | integer | No | Scope rule to a specific context |\n| `description` | string | No | Optional description |\n| `priority` | integer 0–1000 | No | Higher = evaluated first. Default: 100 |\n\n**Example**\n```\nCreate a pin rule called \"Pin Nike\" that pins items where brand equals \"Nike\" to position 3, scoped to context 1\n```\n\n---\n\n### `update_rule` / `delete_rule` / `toggle_rule` / `enable_rule` / `disable_rule`\n\nUpdate, delete, or enable/disable a rule by `rule_id`.\n\n---\n\n### `get_user_analytics`\n\nGet served counts, event breakdown, unique-item activity, and click-through rate for a specific user.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `user_id` | string | Yes | User ID or email to inspect |\n| `context_id` | positive integer | No | Scope to a console-generated context |\n| `window` | `1d` \\| `7d` \\| `30d` \\| `90d` | No | Time window (default `7d`) |\n\n---\n\n### `get_item_analytics`\n\nGet served counts, event breakdown, watch/click counts, and click-through rate for a specific item.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `item_id` | positive integer | Yes | NSL-generated item ID to inspect |\n| `context_id` | positive integer | No | Scope to a console-generated context |\n| `window` | `1d` \\| `7d` \\| `30d` \\| `90d` | No | Time window (default `7d`) |\n\n---\n\n### `compare_items`\n\nCompare two items head-to-head by served count, events, clicks, and CTR over the same time window.\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `item_a_id` | positive integer | Yes | First NSL-generated item ID |\n| `item_b_id` | positive integer | Yes | Second NSL-generated item ID |\n| `context_id` | positive integer | No | Scope to a console-generated context |\n| `window` | `1d` \\| `7d` \\| `30d` \\| `90d` | No | Time window (default `7d`) |\n\n---\n\n### `top_items`\n\nList the top items by served count or by matching event activity over a time window. Use `metric=\"served\"` for generic \"top item\" or \"best performing\" questions. Use `metric=\"events\"` when the user explicitly names an engagement signal (e.g. watch, click, purchase).\n\n**Inputs**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `metric` | `served` \\| `events` | No | Rank by served count or event count (default `served`) |\n| `event_name` | string | No | Event name filter when `metric=events` (e.g. `\"watch\"`, `\"click\"`) |\n| `event_id` | integer | No | Numeric event ID filter when `metric=events` |\n| `context_id` | positive integer | No | Scope to a console-generated context |\n| `window` | `1d` \\| `7d` \\| `30d` \\| `90d` | No | Time window (default `7d`) |\n| `limit` | integer 1–50 | No | Max items to return (default 10) |\n\n**Example**\n```\nWhat's the top item served in the last 7 days?\nWhich items had the most watch events last month?\n```\n\n---\n\n## Authentication\n\n**Public mode** uses [OAuth 2.0 Client Credentials](https://console.neuronsearchlab.com/security). Tokens are fetched on startup, cached in memory, and auto-refreshed 60 seconds before expiry.\n\n**Internal mode** uses a NeuronSearchLab API key with the `admin` scope. Set `NSL_API_KEY` and `NSL_PLATFORM_MODE=internal`.\n\n---\n\n## Development\n\n```bash\ngit clone https://github.com/NeuronSearchLab/mcp\ncd mcp\nnpm install\nexport NSL_CLIENT_ID=your-client-id\nexport NSL_CLIENT_SECRET=your-client-secret\nnpm run dev           # dev mode (tsx, no build)\nnpm run build         # compile to dist/\n```\n\n---\n\n## License\n\nMIT\n",
  "bytes": 20767,
  "sha": "f8c9cfdefb91643a16b146e2f395c5bbcb54a353c1e1ab5988dc880fde9d9af7",
  "repo_slug": "neuronsearchlab/mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_neuronsearchlab_mcp_db318cdf/readme"
}