Skip to main content
Glama
K-Jadeja

@kjadeja/open-featurebase-mcp

by K-Jadeja

@kjadeja/open-featurebase-mcp

A Model Context Protocol (MCP) server I built for reading public Featurebase feedback boards from any MCP-compatible agent — Claude Code, Cursor, VS Code, others.

I built this for Remalt because I wanted my coding agent to be able to answer questions like "what have users been asking for that we haven't replied to?", "which promised fixes are stalled?", and "what's the most-upvoted unaddressed feedback this week?" without me copy-pasting from a browser tab.

The default board is the Remalt one, but it works against any public Featurebase board that exposes the same public listing + comment endpoints.

Install

Quickest path — npx

npx -y @kjadeja/open-featurebase-mcp

This runs the server directly without installing anything. Use this for one-off testing or to confirm the package works on your machine.

To install globally:

npm install -g @kjadeja/open-featurebase-mcp

Then point any MCP client at the binary it adds to your PATH:

which open-featurebase-mcp
# /usr/local/bin/open-featurebase-mcp   (macOS/Linux)
// or on Windows:
where open-featurebase-mcp

Related MCP server: feedback-mcp

Connecting an MCP client

The setup file format differs across clients — pick the one that matches yours.

Claude Code

The simplest setup is the CLI:

# Use the default Remalt board
claude mcp add --transport stdio --scope user featurebase -- npx -y @kjadeja/open-featurebase-mcp

# Or point at a different board
claude mcp add --transport stdio --scope user --env FEATUREBASE_BOARD_URL=https://example.featurebase.app featurebase -- npx -y @kjadeja/open-featurebase-mcp

Native Windows (not WSL)

On native Windows, Claude Code needs cmd /c around local npx MCP servers:

# Use the default Remalt board
claude mcp add --transport stdio --scope user featurebase -- cmd /c npx -y @kjadeja/open-featurebase-mcp

# Or point at a different board
claude mcp add --transport stdio --scope user --env FEATUREBASE_BOARD_URL=https://example.featurebase.app featurebase -- cmd /c npx -y @kjadeja/open-featurebase-mcp

For a project-root .mcp.json on native Windows:

{
  "mcpServers": {
    "featurebase": {
      "command": "cmd",
      "args": [
        "/c",
        "npx",
        "-y",
        "@kjadeja/open-featurebase-mcp"
      ],
      "env": {
        "FEATUREBASE_BOARD_URL": "https://itsremalt.featurebase.app"
      }
    }
  }
}

WSL uses the macOS/Linux form with command: "npx".

If you prefer to keep it in a file, use .mcp.json in the project root with the mcpServers (note the camelCase) key:

{
  "mcpServers": {
    "featurebase": {
      "command": "npx",
      "args": ["-y", "@kjadeja/open-featurebase-mcp"],
      "env": {
        "FEATUREBASE_BOARD_URL": "https://itsremalt.featurebase.app"
      }
    }
  }
}

Cursor

Cursor uses .cursor/mcp.json in the project root, with the mcpServers key:

{
  "mcpServers": {
    "featurebase": {
      "command": "npx",
      "args": ["-y", "@kjadeja/open-featurebase-mcp"],
      "env": {
        "FEATUREBASE_BOARD_URL": "https://itsremalt.featurebase.app"
      }
    }
  }
}

VS Code (GitHub Copilot Chat or other MCP-aware extensions)

VS Code uses .vscode/mcp.json, with a top-level servers (not mcpServers) key:

{
  "servers": {
    "featurebase": {
      "command": "npx",
      "args": ["-y", "@kjadeja/open-featurebase-mcp"],
      "env": {
        "FEATUREBASE_BOARD_URL": "https://itsremalt.featurebase.app"
      }
    }
  }
}

Note: The three file formats are NOT interchangeable. .vscode/mcp.json uses servers; Claude Code and Cursor use mcpServers. Copy the exact form above for your editor.

After editing the file, reload the editor so it picks up the new server. The seven tools below will appear in the MCP tools list.

Configuration

Env var

Default

Purpose

FEATUREBASE_BOARD_URL

https://itsremalt.featurebase.app

The public Featurebase board to read from. Optional — set this only if you want a different board.

FEATUREBASE_TEAM_USER_IDS

(unset)

Comma-separated Featurebase user IDs considered team. Used for admin/customer classification. Optional.

When team IDs matter

Most tools work without any team configuration — they read posts, comments, search, stats, batch-fetch, and user lookup without knowing who's on the team. Team IDs are only needed when you want to classify authors or detect stalled follow-ups:

Tool

Without team IDs

With team IDs

list_featurebase_posts (no hasAdminReply)

✅ Works

✅ Same result

get_featurebase_post

✅ Works; author.role === "unknown"

✅ Authors classified; engagement fields populated

get_featurebase_posts

✅ Works

✅ Authors classified

search_featurebase_posts

✅ Works

✅ Authors classified

get_featurebase_stats

✅ Works

✅ Same result

find_featurebase_user

✅ Works; totalCommentCount still accurate

✅ Same result

list_featurebase_posts(hasAdminReply=…)

❌ Throws InvalidParams

✅ Filters posts

get_featurebase_stalled_promises

⚠️ Returns empty with a warning

✅ Returns stalled promises

When a tool requires a team identity and none is configured, it errors out rather than silently fabricate customer / admin assignments. To enable the team-aware tools, either set FEATUREBASE_TEAM_USER_IDS=id1,id2,… in the env, or call find_featurebase_user with your name to discover IDs and pass them as teamUserIds per-call.

Practical prompts

These are the workflows I actually run. Paste them into Claude Code / Cursor after the MCP server is connected.

Daily triage

Show me the top 10 most-upvoted open posts that don't yet have an admin reply. For each one, summarize the request and quote the highest-voted customer comment.

This uses list_featurebase_posts(hasAdminReply=false, status="open", sortBy="upvotes:desc", teamUserIds=[…]) followed by get_featurebase_post for the top entries.

Find stalled follow-ups

Which posts have I (the team) replied to, the customer replied after me, and I haven't said anything in over a week? Show the last 5 by staleness, with the customer's last message quoted.

This is exactly get_featurebase_stalled_promises({ minDaysSinceAdminReply: 7 }).

Detect duplicates

Search the board for "export to CSV" and "download as spreadsheet". Cluster the matches by similarity and tell me which ones look like duplicates I should merge.

This uses search_featurebase_posts for both queries and then a similarity grouping.

Create a GitHub issue from a feature request

Take post more-byok-options, summarize it as a single-paragraph problem statement, and produce a GitHub-issue-formatted markdown block (title + body) that I can paste into our repo.

The agent reads the post body, formats it, and you paste the result into GitHub.

Voice-of-customer report

Read the 20 most-recent open posts. Group them by theme. For each theme, give me: how many users mentioned it, the total upvotes, and one representative quote.

This uses list_featurebase_posts(status="open", sortBy="date:desc", limit=20) plus per-post comment reads.

Find unanswered posts

List all posts with the in_progress status that have zero admin replies. These are the ones we should respond to first.

This is list_featurebase_posts(hasAdminReply=false, status="in_progress").

Discover your team IDs

Find my user ID on this board. My name is "Krishna".

This uses find_featurebase_user({ name: "Krishna" }). Use the returned IDs as teamUserIds in subsequent calls — no env-var setup needed.

Tools

Seven read-only tools. Each one is designed to be cheap enough to chain — most listing calls don't fetch comments at all unless you ask for engagement.

list_featurebase_posts

Args:

  • status — one of the friendly names below; the server maps them to the underlying postStatus.type values returned by the public board:

    Friendly name

    postStatus.type

    open

    open

    in_review

    reviewing

    planned

    unstarted

    in_progress

    active

    completed

    completed

    The default all skips the filter and returns every status.

  • sortBydate:desc (default), date:asc, or upvotes:desc.

  • limit — 1–200, default 50.

  • hasAdminReply — optional boolean. Requires a team identity (env var or teamUserIds override). If neither is set, the call throws InvalidParams.

  • teamUserIds — optional string[] override for the team.

Returns: { totalResults, availableResults, truncated, returned, posts: NormalizedPost[] }

Behavior:

  • A normal listing call (no hasAdminReply) does not fetch comments and does not populate engagement metadata. It returns posts with author.role === "unknown" when no team is configured.

  • When hasAdminReply is provided, comments are fetched for posts with commentCount > 0 and engagement is computed under the team. Posts with commentCount === 0 are treated as hasAdminReply: false (the team definitively has not replied) without a comment API request.

get_featurebase_post

Args:

  • slug — required (e.g. more-byok-options).

  • include_comments — default false. When true, inlines the full comment thread as comments: NormalizedComment[].

  • teamUserIds — optional string[] override.

Returns: { ...NormalizedPost, contentHtml, contentText, comments?, commentsError? }

contentHtml and contentText are always inlined. If the comments fetch fails, commentsError is set and the post is still returned.

When teamUserIds is supplied, both comment-author roles and engagement fields are reclassified against that team. A non-empty teamUserIds array replaces FEATUREBASE_TEAM_USER_IDS for that call only; an empty array [] is treated as absent (the env var is used if configured).

get_featurebase_posts (batch)

Args: slugs (1–20), include_content (default false).

Returns posts in the order requested; missing slugs go into notFound rather than throwing. Set include_content=true to inline full body on each entry.

search_featurebase_posts

Args: query (required), limit (1–50, default 10).

Returns posts ordered by relevance (title hit = 3 pts, body hit = 1 pt, per-token matches also weighted).

get_featurebase_stats

Args: topVotedLimit (1–50, default 5), recentLimit (1–50, default 5).

Returns: { totalResults, snapshotSize, truncated, snapshotWindow, statusCountsInSnapshot, categoryCountsInSnapshot, topVoted[N], recent[N] }

snapshotWindow is the actual date range currently in the in-memory snapshot — labels like *InSnapshot are explicit that these counts are over the snapshot, not over a complete board snapshot from a single source. The snapshot is built on demand from the public listing endpoint and is fresh as of the first fetch in the current process.

get_featurebase_stalled_promises

Args:

  • minDaysSinceAdminReply — 0–365, default 7.

  • limit — 1–50, default 20.

  • teamUserIds — optional string[] override.

  • status — restrict candidates to one of these statuses.

  • sortBystaleness (default), freshness, or upvotes.

Returns: { minDaysSinceAdminReply, teamSource, warning?, unusedTeamUserIds?, unusedTeamUserIdsComplete?, totalCandidates, returned, promises: StalledPromise[] }

teamSource is "override" (per-call team), "default" (env-var team), or "none" (no team — returns empty with a warning).

unusedTeamUserIds lists IDs you supplied that didn't appear in any comment thread. unusedTeamUserIdsComplete: false signals that some comment fetches failed and we couldn't fully determine unused IDs.

find_featurebase_user

Args: name (≥2 chars, partial match), sampleSize (0–20, default 5).

Returns: { query, samplePostsScanned, commentsComplete, warning?, matches: UserMatch[] }

commentsComplete is true only when every comment fetch for the index build succeeded; false means totals may undercount.

Each UserMatch carries userId, name, postCount, commentCountInSampledPosts, totalCommentCount (board-wide), and guessedRole.

Known limitations

  • Reads only. Posting comments, voting, changing status all require authenticated access to Featurebase — out of scope.

  • Designed for public boards. Works on Remalt and on other public boards that expose the same public listing + comment endpoints. Boards with aggressive bot protection, sign-in walls, or non-standard layouts may not work.

  • No real-time updates. The in-memory snapshot is fresh on first fetch in a given process and cached for 5 minutes. Restart the server to flush.

  • Admin role tagging requires team IDs. Without FEATUREBASE_TEAM_USER_IDS (or a per-call teamUserIds), author roles are "unknown" and hasAdminReply filtering is refused.

How it works (briefly)

  1. The public board exposes /api/v1/submission?…&page=N (the SPA's axios baseURL is /api). The server calls page 1 to learn totalPages and totalResults, then fetches pages 2..N concurrently. Listing pagination is atomic — if any required page fails, the entire tool call surfaces the failure and no partial listing is cached or returned.

  2. /api/v1/comment?submissionId=<id>&page=N returns the comment thread. Comment pagination is also atomic — a single failed page throws and is never cached as a partial thread.

  3. Engagement fields (hasAdminReply, counts, dates) are computed from the classified comment tree. The cache is role-neutral: roles are derived per request against the active team set, never stored on the cached tree.

Troubleshooting

Listing fails with Incomplete listing: failed pages N of M The listing endpoint returned an error on one or more pages. The tool call surfaces this failure — no partial listing is returned or cached. Retry on the same client will refetch every listing page from scratch. This is by design (atomic contract).

engagementComplete: false in a list_featurebase_posts(hasAdminReply=…) response Means one or more specific comment-thread fetches failed during engagement enrichment. The response includes failedPostSlugs listing which posts couldn't be classified. Posts that did succeed are still filtered correctly; only the affected posts get commentFetchFailed: true and are excluded from the filter result. Retry the request after a short delay.

commentsComplete: false in find_featurebase_user At least one post's comments failed to fetch while building the board-wide user-count index. totalCommentCount for users who only appeared in failed threads may undercount. Retry after a short delay.

All author roles show "unknown" No team is configured. Either set FEATUREBASE_TEAM_USER_IDS in the env, or use find_featurebase_user to discover IDs and pass them as teamUserIds per-call.

hasAdminReply filter throws InvalidParams You asked for a team-based filter without providing a team. Set FEATUREBASE_TEAM_USER_IDS or pass teamUserIds to the call.

commentsError is set on a get_featurebase_post response The post is still returned with its body and metadata; only the comments array is missing. Common causes: network error, rate limit, or the comment endpoint returning an unexpected shape.

For contributors

If you want to develop on this:

git clone https://github.com/K-Jadeja/open-featurebase-mcp
cd open-featurebase-mcp
npm ci
npm run build
npm test         # 339 deterministic checks; no live network
npm start        # launches the stdio server

The default npm test is fully offline (mock fetcher fixtures). A separate npm run test:live runs against a live Featurebase endpoint and is opt-in.

License

MIT

Available Tools

6 tools
find_featurebase_userB

Look up user IDs by partial name match.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPartial name to search for, case-insensitive. Minimum 2 characters to avoid matching everything on boards with common one-letter fragments (e.g. 'a' would otherwise surface every user with 'A' in their name). Scans post authors and the comment threads of the N most recent posts with comments. Example: 'Krishna' returns 'Krishna - Remalt Dev' if they've posted or commented on the board.
sampleSizeNoHow many recent posts with comments to scan for comment authors. Default 5 (cached comments make this cheap). Set to 0 to skip comment scanning — only post authors will be returned. Max 20.

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It only states the basic function, omitting behavioral details like case-insensitivity, scanning scope, or what sampleSize does. The schema provides details, but the description itself is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no fluff. It is appropriately sized for the tool's simplicity, though could slightly expand on behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks return value information (no output schema). Given the tool's simplicity and sibling context, it is incomplete for an agent to fully understand the outcome.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline 3. The description does not add meaning beyond the schema; both parameters are fully described in the schema, so no extra value from the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('look up') and resource ('user IDs') with a clear method ('partial name match'). It distinguishes itself from sibling tools, which all relate to posts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for user ID lookup without explicit guidance on when to use versus alternatives. Since all siblings are post-related, context is clear, but no exclusions or when-not-to-use are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_featurebase_postB

Get a single post by slug, optionally with full comment thread.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugYesThe post slug (the URL path segment after /posts/). Example: 'more-byok-options'
teamUserIdsNoOptional override for the team-user-id set. When provided as a NON-EMPTY array, comments (and engagement fields on the post) are re-classified using these IDs as the team — useful for drilling into a single thread after calling find_featurebase_user. A non-empty override REPLACES the FEATUREBASE_TEAM_USER_IDS env var for this call only. An EMPTY array ([]) is treated as ABSENT — the env var is used if configured. With no env var configured AND no teamUserIds passed, comment authors will show role='unknown' and engagement fields will be omitted.
include_commentsNoIf true, fetch and inline the full comment thread as a `comments` array on the response (nested with `replies`). Each comment carries author (name, userId, role='admin'|'customer'|'unknown'), bodyHtml, bodyText, createdAt, updatedAt, upvotes, parentId, and replies[]. On fetch failure the post is still returned with `commentsError` set. Default: false.

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It only mentions the basic functionality and optional comment inclusion, omitting key behaviors like error handling (e.g., if slug is not found), authorization requirements, or whether it is a read-only operation. The parameter documentation provides some detail but the main description lacks transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence of 16 words, efficiently conveying the core purpose. It is front-loaded and lacks fluff, though it could benefit from an extra sentence about usage context without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is too minimal given the tool's complexity (3 parameters, no output schema). It does not outline the return structure of the post object or the comments data, leaving the agent to infer from the parameter descriptions. Crucial information like required authentication or possible error responses is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with detailed descriptions for all three parameters. The main description adds only the high-level idea of 'optionally with full comment thread,' which is already implied by the 'include_comments' parameter. Baseline 3 is appropriate as the description adds minimal value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Get a single post by slug, optionally with full comment thread,' using a specific verb and resource. It clearly distinguishes from sibling tools like 'get_featurebase_posts' (plural) which would fetch multiple posts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for retrieving a specific post given a slug, but it does not explicitly state when to use this tool over alternatives like 'list_featurebase_posts' or 'search_featurebase_posts'. No exclusions or when-not-to-use guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_featurebase_postsA

Batch-fetch multiple posts by slug array.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugsYesArray of post slugs to fetch. Returns posts in the order requested. Slugs not in the snapshot are returned in the `notFound` field rather than throwing.
include_contentNoIf true, attach full contentHtml + contentText to each post INLINE on posts[i] (mirrors the singular get_featurebase_post shape — same fields, just on each element). Off by default — the 800-char excerpt is usually enough for clustering/dedup work. Turn on only when you need the full body.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses that posts are returned in order requested and that missing slugs are returned in a 'notFound' field rather than throwing. No mention of auth, rate limits, or destructive behavior. Given read-like name, transparency is good but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main description is a single sentence with no waste. Parameter descriptions are thorough yet concise. Every sentence adds value, effectively balancing brevity with necessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema. Description covers ordering and notFound behavior but does not detail the full return structure (e.g., which fields each post object contains). While sibling 'get_featurebase_post' may document shape, the tool alone leaves some gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds significant meaning: for 'slugs', it explains ordering and error handling; for 'include_content', it clarifies when to enable and the trade-off with excerpt length. This exceeds baseline expectations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the action 'Batch-fetch', the resource 'posts', and the method 'by slug array'. It clearly distinguishes from sibling tools like 'get_featurebase_post' (singular) and 'list_featurebase_posts' (likely without slugs).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or alternatives mentioned for tool selection. The 'include_content' parameter provides usage guidance (e.g., 'Off by default — the 800-char excerpt is usually enough... Turn on only when you need the full body'), but overall guidance is minimal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_featurebase_stalled_promisesC

Find posts where admin replied, customer spoke last, admin silent for N+ days.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of stalled promises to return (1-50). Default: 20.
sortByNoSort order for returned stalled promises. 'staleness' (default): customerLastReplyDate desc — most-recent stalled promises first. 'freshness': adminLastReplyDate desc — most-recent admin replies first (catch up on what you just said). 'upvotes': upvotes desc — focus on high-impact items regardless of staleness.staleness
statusNoRestrict candidates to posts with these statuses (e.g. ['in_progress', 'in_review'] to exclude Completed and Planned). When omitted, all statuses are eligible.
teamUserIdsNoOptional override for the team-user-id set. When provided as a NON-EMPTY array, these IDs REPLACE the FEATUREBASE_TEAM_USER_IDS env var for this call only — the env var is ignored. Use this together with find_featurebase_user to run a stalled-promise query without env-var configuration. An EMPTY array ([]) is treated as ABSENT — the env var team is used if configured; otherwise stalled-promises returns immediately with teamSource='none' and a warning. Engagement fields are re-computed on the fly from cached comments using this set.
minDaysSinceAdminReplyNoMinimum number of days since the admin's last reply for a post to qualify as a stalled promise. Default: 7. Set to 0 to surface every post where the customer spoke last, regardless of age.

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description must disclose behavioral traits. It only states the high-level purpose. It does not mention how teamUserIds override works, sorting behavior, or any side effects. The schema descriptions compensate, but the tool description itself is insufficient for behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that is easy to parse and front-loaded. It avoids unnecessary words. However, it could be slightly more structured (e.g., mentioning key parameters like default N days) without losing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 5 parameters, no output schema, and moderate complexity (team override, sorting, status filter), the one-sentence description is too minimal. It does not explain output format, behavior of the 'N' parameter, or nuance like empty teamUserIds. The description is incomplete for an agent to fully understand the tool's capabilities.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed parameter descriptions. The tool description adds no parameter info beyond what the schema provides. Per rubric, baseline 3 is appropriate since the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool finds posts where admin replied, customer spoke last, and admin is silent for N+ days. It identifies the specific resource (stalled promises) and verb (find). However, it does not explicitly differentiate from sibling tools like list_featurebase_posts or search_featurebase_posts, which could also retrieve posts with conditions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool vs alternatives. The description lacks information about prerequisites (e.g., need for FEATUREBASE_TEAM_USER_IDS env var) or scenarios where this tool is inappropriate. Sibling tool names are listed but not contrasted.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_featurebase_postsB

List posts on the configured Featurebase feedback board.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of posts to return (1-200).
sortByNoSort order for results.date:desc
statusNoFilter by Featurebase status. Values map to underlying postStatus.type as: in_review → 'reviewing', planned → 'unstarted', in_progress → 'active', completed → 'completed', open → 'open'.all
teamUserIdsNoOptional override for the team-user-id set. When provided as a NON-EMPTY array, this list of IDs is treated as the team for hasAdminReply classification, REPLACING the FEATUREBASE_TEAM_USER_IDS env var for this call only. An EMPTY array ([]) is treated as ABSENT — the env var is used if configured, otherwise the request still fails with InvalidParams for hasAdminReply. Useful after a find_featurebase_user drill-down — pass the returned userIds here to filter the listing by team engagement without re-reading the env.
hasAdminReplyNoWhen true, restrict to posts where the team has authored at least one comment (hasAdminReply === true). When false, restrict to posts where the team has NOT commented. REQUIRES a team identity — if no team is available (FEATUREBASE_TEAM_USER_IDS unset AND no teamUserIds override supplied), the request FAILS with InvalidParams rather than silently returning an empty list. Fabricating hasAdminReply=false for every post would be a silent false-positive for callers asking for hasAdminReply:false, and a silent false-negative for callers asking for hasAdminReply:true. Call find_featurebase_user first to discover user IDs, then pass them as teamUserIds.

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, and the description lacks details on behavioral traits such as rate limits, authentication requirements, or potential side effects. It assumes a 'configured' board without explaining setup.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The own description is concise, but extensive parameter details follow. The structure is front-loaded with the core purpose and then detailed parameter info, which is appropriate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

While parameter documentation is thorough, the description omits output format, pagination details beyond limit, and error scenarios. Given the lack of output schema, more completeness on return values is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers parameters fully (100% coverage). The description adds significant value by explaining complex behaviors of teamUserIds and hasAdminReply, especially the override logic and error handling.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists posts from the configured Featurebase board. However, it does not differentiate from sibling tools like get_featurebase_posts or search_featurebase_posts, which likely have similar listing capabilities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. The description does not mention prerequisites, when not to use, or any context for selection among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_featurebase_postsA

Search posts by keyword over title + body.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of results to return (1-50).
queryYesKeyword or phrase to search for. Matches against post titles (weighted 3x) and bodies (1x). Multi-word queries are tokenized.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden of behavioral disclosure. It states the search scope (title + body), which is helpful, but does not explicitly indicate that the operation is read-only or describe any other behavioral traits. The weighting and tokenization details are in the schema parameter descriptions, but the tool description itself lacks transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence with no filler or extraneous information. Every word contributes to the tool's purpose, making it highly concise and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple search tool with a complete schema, the description covers the core purpose but omits contextual details like result format, sorting, or when to prefer this over other retrieval tools. It is minimally adequate but not fully comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The tool description adds minimal context ('by keyword over title + body') beyond what the schema already provides (weighting, tokenization). Thus, it meets the baseline but does not significantly enhance understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Search') and the resource ('posts'), and specifies the scope ('by keyword over title + body'). This effectively distinguishes it from sibling tools like list_featurebase_posts (which would list all) and get_featurebase_post (which retrieves by ID).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives (e.g., when to search vs list or get). There is no mention of prerequisites, context, or when not to use it, leaving the agent with insufficient decision-making information.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv1.0.2
    • First observedfind_featurebase_user
    • First observedget_featurebase_post
    • First observedget_featurebase_posts
    • First observedget_featurebase_stalled_promises
    • First observedlist_featurebase_posts
    • First observedsearch_featurebase_posts

TDQS

A3.5/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: batch fetch by slugs, list all, get single, search, find stalled promises, and user lookup. No overlap in functionality.

Naming Consistency4/5

All tools follow a verb_featurebase_noun pattern, but verbs like 'get' are used for multiple actions (batch, single, stalled promises) and 'find' vs 'search' introduces minor inconsistency.

Tool Count5/5

Six tools is well-scoped for a Featurebase integration, covering core read operations and a specialized query without being overwhelming or insufficient.

Completeness3/5

The tool set covers reading and searching well, but lacks any write operations (create, update, delete) for posts or comments, which are typical for a feedback board.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for Stack Overflow for Agents, enabling search, post creation, voting, and knowledge exchange for AI agents.
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for Open Feedback, enabling AI assistants to submit, list, get, update status of, and analyze product feedback via a local HTTP API and JSONL storage.
    346 npm
    Apache 2.0
  • F
    license
    Not graded
    quality
    B
    maintenance
    Agent-native MCP server for a tiny social feed of technical founders. Enables read, post, reply, react, and agent collaboration features like catching up, trading conviction, and managing tracks.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Official MCP server for FeatureJet, enabling agents to read and act on customer feedback boards: list/search posts, file feature requests, and pull top-voted planned items.
    MIT