Koskamo

stackexchange-mcp-server

An MCP server that allows agents to search Stack Exchange sites, retrieve full Q&A threads as markdown, browse tag FAQs, and look up user profiles. It supports STDIO and Streamable HTTP transports and provides tools for listing sites, searching questions with filters, and fetching detailed thread content.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

stackexchange-mcp-server logo, by cyanheadsCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-06Published by cyanheads
MCP endpoint (Streamable HTTP)
https://stackexchange.caseyjhand.com/mcp
Vendor documentation

What its tools do

5 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

5 of 5 have a description · 5 of 5 declare behavior hints · 5 of 5 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Search questions across Stack Exchange sites with full-text queries and tag filters
  • Fetch complete Q&A threads as clean markdown for detailed reading
  • Browse tag FAQs to find frequently asked questions on specific topics
  • Look up user profiles to see reputation, badges, and top tags

Source and maintenance

Community listingRegistry 0.2.0
Maintenance checked

Protocol and capabilities

Server
stackexchange-mcp-server 0.2.0
MCP protocol negotiated in check
2025-11-25
Tools
5 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
0 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "logging": {},
  "prompts": {
    "listChanged": true
  },
  "resources": {
    "subscribe": true,
    "listChanged": true
  },
  "extensions": {
    "io.modelcontextprotocol/skills": {
      "directoryRead": true
    }
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Use stackexchange_list_sites to find a community, then stackexchange_search_questions or stackexchange_get_tag_faq to discover question IDs. Read full Q&A content with stackexchange_get_thread, and pass an authorUserId to stackexchange_get_user for author context.

Tools

5 advertised

stackexchange_list_sites — List Stack Exchange Sites
Advertised by the server during the last successful anonymous check.
Advertised read-only

Enumerate all sites in the Stack Exchange network — name, api_site_parameter, audience, and URL. The api_site_parameter value is what other tools accept as the `site` input (e.g. "stackoverflow", "superuser", "serverfault"). Results are fetched live and optionally filtered by name. Use this tool to discover valid site parameters before calling other stackexchange_* tools.

stackexchange_list_sites input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "filter": {
      "type": "string",
      "description": "Optional case-insensitive name filter — returns only sites whose name contains all provided tokens. Omit to return all sites."
    }
  },
  "additionalProperties": false
}
stackexchange_list_sites output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "sites",
        "totalCount",
        "quotaRemaining",
        "quotaMax"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "quota_exceeded",
                "throttled",
                "pacer_shed",
                "invalid_parameter",
                "invalid_api_key",
                "upstream_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `quota_exceeded`: The Stack Exchange API quota_remaining reached 0 during the site page walk. `throttled`: Stack Exchange is throttling this server's IP address, or its backoff window outlasts what the call can wait. `pacer_shed`: The call would wait in this server's queue to Stack Exchange longer than its time budget allows. `invalid_parameter`: Stack Exchange rejected a parameter of the /sites request and named the field. `invalid_api_key`: Stack Exchange does not recognize the API key this server is configured with. `upstream_unavailable`: Stack Exchange reported itself temporarily unavailable or failing internally, or answered with a body that is not the expected JSON envelope. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "sites": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "apiSiteParameter",
          "siteUrl"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable site name (e.g. \"Stack Overflow\")."
          },
          "siteUrl": {
            "type": "string",
            "description": "Public URL of the site."
          },
          "audience": {
            "type": "string",
            "description": "Intended audience description when provided by the API."
          },
          "apiSiteParameter": {
            "type": "string",
            "description": "Value to pass as the `site` parameter on all other stackexchange_* tools (e.g. \"stackoverflow\")."
          }
        },
        "description": "A Stack Exchange network site entry.",
        "additionalProperties": false
      },
      "description": "Stack Exchange network sites matching the optional name filter."
    },
    "notice": {
      "type": "string",
      "description": "Actionable guidance when results are empty or filtered."
    },
    "quotaMax": {
      "type": "number",
      "description": "Maximum API quota calls per day (300 keyless, ~10,000 with API key)."
    },
    "totalCount": {
      "type": "number",
      "description": "Total number of sites returned after filtering."
    },
    "quotaRemaining": {
      "type": "number",
      "description": "Remaining API quota calls for the current day."
    }
  },
  "additionalProperties": false
}
stackexchange_list_sites annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
stackexchange_search_questions — Search Stack Exchange Questions
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search questions across a Stack Exchange site. Returns ranked questions with title, score, answer count, accepted status, tags, ask and last-activity dates, and a short excerpt of the question body — not the full body. Results supply question_id values for stackexchange_get_thread, which fetches the full question body and all answers. Results past the pageSize cap are reachable with the `page` parameter. Use the `site` parameter to target a specific community (e.g. "stackoverflow", "superuser", "unix"); call stackexchange_list_sites to discover valid site values.

stackexchange_search_questions input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "page": {
      "type": "integer",
      "default": 1,
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Page of results to return, 1-based (default 1). Page 2 with pageSize 10 returns results 11–20. Each page is a separate upstream call and costs one API quota unit, which matters on the keyless 300/day tier. Without STACKEXCHANGE_API_KEY, Stack Exchange refuses any page above 25."
    },
    "site": {
      "type": "string",
      "default": "stackoverflow",
      "description": "Stack Exchange site to search — the api_site_parameter (e.g. \"stackoverflow\", \"superuser\", \"serverfault\") or the site's domain (e.g. \"serverfault.com\"). Defaults to \"stackoverflow\". Call stackexchange_list_sites to discover valid values."
    },
    "sort": {
      "enum": [
        "relevance",
        "votes",
        "activity",
        "newest"
      ],
      "type": "string",
      "default": "relevance",
      "description": "Result ordering: \"relevance\" (default, best match), \"votes\" (highest score first), \"activity\" (most recently active), \"newest\" (most recently created)."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "A single tag to filter by (e.g. \"python\", \"async\")."
      },
      "description": "Filter results to questions with all specified tags."
    },
    "query": {
      "type": "string",
      "description": "Full-text search query (e.g. \"python async generator send value\")."
    },
    "minScore": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Minimum question score — excludes questions with lower scores. Setting minScore orders results by score (votes), which may differ from the requested sort."
    },
    "pageSize": {
      "type": "integer",
      "default": 10,
      "maximum": 30,
      "minimum": 1,
      "description": "Number of results to return (1–30, default 10)."
    },
    "acceptedOnly": {
      "type": "boolean",
      "description": "When true, return only questions that have an accepted answer."
    }
  },
  "additionalProperties": false
}
stackexchange_search_questions output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "questions",
        "page",
        "attribution",
        "quotaRemaining",
        "quotaMax",
        "appliedSort"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "cap": {
      "type": "number",
      "description": "The pageSize cap applied to this request."
    },
    "page": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "The 1-based page these results came from — 1 when the input omitted page."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_site",
                "invalid_parameter",
                "quota_exceeded",
                "throttled",
                "pacer_shed",
                "paging_depth_limit",
                "invalid_api_key",
                "upstream_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_site`: The provided site value is not a valid Stack Exchange network site identifier. `invalid_parameter`: Stack Exchange rejected a request parameter and named the field rather than reporting a bad site. `quota_exceeded`: The Stack Exchange API quota_remaining has reached 0. `throttled`: Stack Exchange is throttling this server's IP address, or its backoff window outlasts what the call can wait. `pacer_shed`: The call would wait in this server's queue to Stack Exchange longer than its time budget allows. `paging_depth_limit`: Stack Exchange refused the requested page because paging above page 25 needs a key. `invalid_api_key`: Stack Exchange does not recognize the API key this server is configured with. `upstream_unavailable`: Stack Exchange reported itself temporarily unavailable or failing internally, or answered with a body that is not the expected JSON envelope. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "shown": {
      "type": "number",
      "description": "Number of results returned."
    },
    "notice": {
      "type": "string",
      "description": "Actionable guidance when results are empty or filtered."
    },
    "quotaMax": {
      "type": "number",
      "description": "Maximum API quota calls per day (300 keyless, ~10,000 with API key)."
    },
    "questions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "questionId",
          "title",
          "link",
          "score",
          "answerCount",
          "isAnswered",
          "tags"
        ],
        "properties": {
          "link": {
            "type": "string",
            "description": "Direct URL to the question."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A tag applied to this question."
            },
            "description": "Tags applied to this question."
          },
          "score": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Question score (upvotes minus downvotes)."
          },
          "title": {
            "type": "string",
            "description": "Question title."
          },
          "excerpt": {
            "type": "string",
            "description": "Opening prose of the question body, trimmed to roughly 300 characters and ending in \"…\" when cut. Code blocks and markdown structure are omitted; absent when the question body is nothing but code."
          },
          "isAnswered": {
            "type": "boolean",
            "description": "True when the question has an accepted answer or at least one positively-scored answer."
          },
          "questionId": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Question ID — pass to stackexchange_get_thread to fetch the full thread."
          },
          "answerCount": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Total number of answers."
          },
          "creationDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the question was asked — use it to judge whether the advice is still current."
          },
          "lastActivityDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of the most recent activity on the question (edit, answer, or comment)."
          }
        },
        "description": "A Stack Exchange question with score, answer count, tags, dates, and optional excerpt.",
        "additionalProperties": false
      },
      "description": "Questions matching the search query, ordered by the specified sort."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when results were capped at pageSize."
    },
    "appliedSort": {
      "enum": [
        "relevance",
        "votes",
        "activity",
        "newest"
      ],
      "type": "string",
      "description": "Sort Stack Exchange applied to these results."
    },
    "attribution": {
      "type": "string",
      "description": "Content license notice. Stack Exchange content is licensed under CC BY-SA 4.0 and requires attribution."
    },
    "quotaRemaining": {
      "type": "number",
      "description": "Remaining API quota calls for the current day."
    },
    "sortOverrideReason": {
      "type": "string",
      "description": "Present only when appliedSort differs from the requested sort; says why."
    }
  },
  "additionalProperties": false
}
stackexchange_search_questions annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true
}
stackexchange_get_tag_faq — Get Stack Exchange Tag FAQ
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch the frequently asked questions for a tag on a Stack Exchange site — Stack Exchange's own "frequently asked" selection, returned in its order, not ranked by score; compare the scores yourself. Returns a question list without bodies; use stackexchange_get_thread to read the full body and answers for any result. Results past the pageSize cap are reachable with the `page` parameter. Use this tool to find the questions a community keeps coming back to on a topic (e.g. tag "javascript" on stackoverflow). Use stackexchange_search_questions for free-text search rather than tag-based browsing.

stackexchange_get_tag_faq input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "tag"
  ],
  "properties": {
    "tag": {
      "type": "string",
      "description": "Tag to look up (e.g. \"python\", \"javascript\", \"docker\"). Must match exactly."
    },
    "page": {
      "type": "integer",
      "default": 1,
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Page of results to return, 1-based (default 1). Page 2 with pageSize 10 returns results 11–20. Each page is a separate upstream call and costs one API quota unit, which matters on the keyless 300/day tier. Without STACKEXCHANGE_API_KEY, Stack Exchange refuses any page above 25."
    },
    "site": {
      "type": "string",
      "default": "stackoverflow",
      "description": "Stack Exchange site — the api_site_parameter (e.g. \"stackoverflow\", \"superuser\") or the site's domain (e.g. \"superuser.com\"). Defaults to \"stackoverflow\". Call stackexchange_list_sites to discover valid values."
    },
    "pageSize": {
      "type": "integer",
      "default": 10,
      "maximum": 30,
      "minimum": 1,
      "description": "Number of results to return (1–30, default 10)."
    }
  },
  "additionalProperties": false
}
stackexchange_get_tag_faq output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "questions",
        "tag",
        "site",
        "page",
        "attribution",
        "quotaRemaining",
        "quotaMax"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "cap": {
      "type": "number",
      "description": "The pageSize cap applied to this request."
    },
    "tag": {
      "type": "string",
      "description": "Tag name used for this FAQ lookup."
    },
    "page": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "The 1-based page these results came from — 1 when the input omitted page."
    },
    "site": {
      "type": "string",
      "description": "Stack Exchange site used for this lookup, as passed in site."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_site",
                "invalid_parameter",
                "quota_exceeded",
                "throttled",
                "pacer_shed",
                "paging_depth_limit",
                "invalid_api_key",
                "upstream_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_site`: The provided site value is not a valid Stack Exchange network site identifier. `invalid_parameter`: Stack Exchange rejected a request parameter and named the field rather than reporting a bad site. `quota_exceeded`: The Stack Exchange API quota_remaining has reached 0. `throttled`: Stack Exchange is throttling this server's IP address, or its backoff window outlasts what the call can wait. `pacer_shed`: The call would wait in this server's queue to Stack Exchange longer than its time budget allows. `paging_depth_limit`: Stack Exchange refused the requested page because paging above page 25 needs a key. `invalid_api_key`: Stack Exchange does not recognize the API key this server is configured with. `upstream_unavailable`: Stack Exchange reported itself temporarily unavailable or failing internally, or answered with a body that is not the expected JSON envelope. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "shown": {
      "type": "number",
      "description": "Number of results returned."
    },
    "notice": {
      "type": "string",
      "description": "Actionable guidance when results are empty or filtered."
    },
    "quotaMax": {
      "type": "number",
      "description": "Maximum API quota calls per day (300 keyless, ~10,000 with API key)."
    },
    "questions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "questionId",
          "title",
          "link",
          "score",
          "answerCount",
          "isAnswered",
          "tags"
        ],
        "properties": {
          "link": {
            "type": "string",
            "description": "Direct URL to the question."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A tag applied to this question."
            },
            "description": "Tags applied to this question."
          },
          "score": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Question score (upvotes minus downvotes)."
          },
          "title": {
            "type": "string",
            "description": "Question title."
          },
          "isAnswered": {
            "type": "boolean",
            "description": "True when the question has an accepted answer or at least one positively-scored answer."
          },
          "questionId": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Question ID — pass to stackexchange_get_thread to fetch the full thread."
          },
          "answerCount": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Total number of answers."
          },
          "creationDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the question was asked — use it to judge whether the advice is still current."
          },
          "lastActivityDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of the most recent activity on the question (edit, answer, or comment)."
          }
        },
        "description": "A Stack Exchange FAQ question with score, answer count, tags, and dates.",
        "additionalProperties": false
      },
      "description": "The frequently asked questions for the specified tag, in Stack Exchange's order — not sorted by score."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when results were capped at pageSize."
    },
    "attribution": {
      "type": "string",
      "description": "Content license notice. Stack Exchange content is licensed under CC BY-SA 4.0 and requires attribution."
    },
    "quotaRemaining": {
      "type": "number",
      "description": "Remaining API quota calls for the current day."
    }
  },
  "additionalProperties": false
}
stackexchange_get_tag_faq annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true
}
stackexchange_get_user — Get Stack Exchange User Profile
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch a Stack Exchange user profile by numeric user ID: reputation, badge counts, answer and question counts, account and last-access dates, and top tags by answer score. Useful for credibility context on an answer author — pass the authorUserId from any question or answer in stackexchange_get_thread output. Returns profile fields plus up to 10 top tags by answer score.

stackexchange_get_user input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "userId"
  ],
  "properties": {
    "site": {
      "type": "string",
      "default": "stackoverflow",
      "description": "Stack Exchange site the user ID belongs to — the api_site_parameter (e.g. \"stackoverflow\", \"superuser\") or the site's domain (e.g. \"superuser.com\"). User IDs are per-site, so pass the site of the thread the authorUserId came from. Defaults to \"stackoverflow\". Call stackexchange_list_sites to discover valid values."
    },
    "userId": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Numeric user ID (at most 2147483647) — use the authorUserId field from a question or answer in stackexchange_get_thread output."
    }
  },
  "additionalProperties": false
}
stackexchange_get_user output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "userId",
        "displayName",
        "link",
        "reputation",
        "topTags",
        "quotaRemaining",
        "quotaMax"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "link": {
      "type": "string",
      "description": "Direct URL to the user profile."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "user_not_found",
                "invalid_user_id",
                "invalid_site",
                "invalid_parameter",
                "quota_exceeded",
                "throttled",
                "pacer_shed",
                "invalid_api_key",
                "upstream_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `user_not_found`: The user lookup returns an empty result set — SE returns HTTP 200 with no items for unknown user IDs rather than 404. `invalid_user_id`: userId is above 2147483647 — Stack Exchange user IDs are 32-bit signed integers. `invalid_site`: The provided site value is not a valid Stack Exchange network site identifier. `invalid_parameter`: Stack Exchange rejected a request parameter and named the field rather than reporting a bad site. `quota_exceeded`: The Stack Exchange API quota_remaining has reached 0. `throttled`: Stack Exchange is throttling this server's IP address, or its backoff window outlasts what the call can wait. `pacer_shed`: The call would wait in this server's queue to Stack Exchange longer than its time budget allows. `invalid_api_key`: Stack Exchange does not recognize the API key this server is configured with. `upstream_unavailable`: Stack Exchange reported itself temporarily unavailable or failing internally, or answered with a body that is not the expected JSON envelope. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "userId": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Numeric user ID on this Stack Exchange site."
    },
    "topTags": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "tagName"
        ],
        "properties": {
          "tagName": {
            "type": "string",
            "description": "Tag name."
          },
          "answerCount": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Number of answers in this tag."
          },
          "answerScore": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Total answer score in this tag."
          }
        },
        "description": "A tag the user has answered in, with answer count and score.",
        "additionalProperties": false
      },
      "description": "Top tags by answer score (up to 10). Empty array for new users with no answers."
    },
    "location": {
      "type": "string",
      "description": "User-provided location string when available."
    },
    "quotaMax": {
      "type": "number",
      "description": "Maximum API quota calls per day (300 keyless, ~10,000 with API key)."
    },
    "reputation": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "User reputation score."
    },
    "websiteUrl": {
      "type": "string",
      "description": "User-provided website URL when available."
    },
    "answerCount": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Total number of answers posted when provided by the API."
    },
    "badgeCounts": {
      "type": "object",
      "properties": {
        "gold": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Number of gold badges."
        },
        "bronze": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Number of bronze badges."
        },
        "silver": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Number of silver badges."
        }
      },
      "description": "Badge counts when provided by the API.",
      "additionalProperties": false
    },
    "displayName": {
      "type": "string",
      "description": "Display name shown on the site."
    },
    "creationDate": {
      "type": "string",
      "description": "ISO 8601 timestamp of when the account was created — the account age."
    },
    "questionCount": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Total number of questions posted when provided by the API."
    },
    "lastAccessDate": {
      "type": "string",
      "description": "ISO 8601 timestamp of the last time the user accessed the site — a stale value means the author is unlikely to respond."
    },
    "quotaRemaining": {
      "type": "number",
      "description": "Remaining API quota calls for the current day."
    }
  },
  "additionalProperties": false
}
stackexchange_get_user annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true
}
stackexchange_get_thread — Get Stack Exchange Q&A Thread
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch a complete Q&A thread — question body and all answers, accepted answer first then sorted by score, rendered as clean markdown with fenced code blocks. Accepts a full Stack Exchange question URL, which is read from the site its host names (e.g. "https://unix.stackexchange.com/questions/88490/how-do-i-use-a-heredoc"), or an integer question ID read from site (e.g. "11227809"). HTML is normalized to markdown automatically; attribution (author + link) included per CC BY-SA 4.0. Get question IDs from stackexchange_search_questions or stackexchange_get_tag_faq.

stackexchange_get_thread input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "questionIdOrUrl"
  ],
  "properties": {
    "site": {
      "type": "string",
      "description": "Stack Exchange site a numeric question ID belongs to — the api_site_parameter (e.g. \"stackoverflow\", \"unix\") or the site's domain (e.g. \"unix.stackexchange.com\"). Defaults to \"stackoverflow\". Not needed with a URL, which names its own site: a site naming a different one is ignored, or used when the URL host is not a Stack Exchange site, and either way reported as siteConflict. Call stackexchange_list_sites to discover valid values."
    },
    "maxAnswers": {
      "type": "integer",
      "default": 10,
      "maximum": 100,
      "minimum": 1,
      "description": "Maximum number of answers to include (1–100, default 10). Answers are sorted: accepted first, then by score."
    },
    "includeComments": {
      "type": "boolean",
      "default": false,
      "description": "Fetch the comment thread under the question and under every returned answer (default false). Comments are where a stale answer usually gets corrected (\"this breaks on v3\", \"use X instead now\"), so set this when the answer's continued accuracy matters. Costs 2 extra API calls against the daily quota regardless of how many answers are returned."
    },
    "questionIdOrUrl": {
      "type": "string",
      "description": "Numeric question ID (e.g. \"11227809\") or a full Stack Exchange question URL (e.g. \"https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster\"). A URL carries its own site: the question is read from the URL's host, so question IDs from any Stack Exchange site resolve correctly. A URL whose host is not a Stack Exchange site is read from site when one is given, and fails as invalid_site otherwise."
    }
  },
  "additionalProperties": false
}
stackexchange_get_thread output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "questionId",
        "title",
        "link",
        "score",
        "tags",
        "bodyMarkdown",
        "answers",
        "quotaRemaining",
        "quotaMax"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "cap": {
      "type": "number",
      "description": "The maxAnswers cap applied to this request."
    },
    "link": {
      "type": "string",
      "description": "Direct URL to the question."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "A tag applied to this question."
      },
      "description": "Tags applied to this question."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "question_not_found",
                "invalid_site",
                "invalid_id_or_url",
                "invalid_parameter",
                "quota_exceeded",
                "throttled",
                "pacer_shed",
                "invalid_api_key",
                "upstream_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `question_not_found`: The question lookup returns an empty result set — SE returns HTTP 200 with no items for unknown question IDs rather than 404. `invalid_site`: The site value, or the host of a question URL, is not a Stack Exchange network site. `invalid_id_or_url`: The input is neither an integer ID nor text holding a /questions/{id} path, or Stack Exchange refused the ID. `invalid_parameter`: Stack Exchange rejected a request parameter other than the question ID, and named the field. `quota_exceeded`: The Stack Exchange API quota_remaining has reached 0. `throttled`: Stack Exchange is throttling this server's IP address, or its backoff window outlasts what the call can wait. `pacer_shed`: The call would wait in this server's queue to Stack Exchange longer than its time budget allows. `invalid_api_key`: Stack Exchange does not recognize the API key this server is configured with. `upstream_unavailable`: Stack Exchange reported itself temporarily unavailable or failing internally, or answered with a body that is not the expected JSON envelope. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "score": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Question score (upvotes minus downvotes)."
    },
    "shown": {
      "type": "number",
      "description": "Number of answers returned."
    },
    "title": {
      "type": "string",
      "description": "Question title."
    },
    "answers": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "answerId",
          "score",
          "isAccepted",
          "bodyMarkdown"
        ],
        "properties": {
          "score": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Answer score (upvotes minus downvotes)."
          },
          "answerId": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Numeric answer ID."
          },
          "comments": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "commentId",
                "score",
                "bodyMarkdown"
              ],
              "properties": {
                "score": {
                  "type": "integer",
                  "maximum": 9007199254740991,
                  "minimum": -9007199254740991,
                  "description": "Comment score — comments can score below zero."
                },
                "commentId": {
                  "type": "integer",
                  "maximum": 9007199254740991,
                  "minimum": -9007199254740991,
                  "description": "Numeric comment ID."
                },
                "authorLink": {
                  "type": "string",
                  "description": "Comment author profile URL when available."
                },
                "authorName": {
                  "type": "string",
                  "description": "Comment author display name when available."
                },
                "bodyMarkdown": {
                  "type": "string",
                  "description": "Comment body normalized from HTML to markdown."
                },
                "creationDate": {
                  "type": "string",
                  "description": "ISO 8601 timestamp of when the comment was posted — the newest comments carry the freshest corrections."
                }
              },
              "description": "A single comment with markdown body, score, date, and author attribution.",
              "additionalProperties": false
            },
            "description": "Comments on this answer, newest first, present only when includeComments is true. An empty array means this post has no comments; an absent array means its comment state is unknown — either comments were not requested, or the batched fetch was cut short before this post contributed any. Never read an absent array as \"no comments\"."
          },
          "authorLink": {
            "type": "string",
            "description": "Answer author profile URL when available."
          },
          "authorName": {
            "type": "string",
            "description": "Answer author display name when available."
          },
          "isAccepted": {
            "type": "boolean",
            "description": "True when this is the accepted answer."
          },
          "authorUserId": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Answer author numeric user ID when available — pass to stackexchange_get_user to fetch the full profile."
          },
          "bodyMarkdown": {
            "type": "string",
            "description": "Answer body normalized from HTML to markdown."
          },
          "creationDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the answer was posted — an old answer may predate the current API."
          },
          "authorReputation": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Answer author reputation when available."
          },
          "lastActivityDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of the most recent edit or activity on the answer."
          },
          "commentsTruncated": {
            "type": "boolean",
            "description": "True when this answer's comments[] is a partial list — more exist upstream than were returned."
          }
        },
        "description": "A single Q&A answer with markdown body, score, dates, and author attribution.",
        "additionalProperties": false
      },
      "description": "Answers sorted: accepted answer first, then by score descending."
    },
    "comments": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "commentId",
          "score",
          "bodyMarkdown"
        ],
        "properties": {
          "score": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Comment score — comments can score below zero."
          },
          "commentId": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "description": "Numeric comment ID."
          },
          "authorLink": {
            "type": "string",
            "description": "Comment author profile URL when available."
          },
          "authorName": {
            "type": "string",
            "description": "Comment author display name when available."
          },
          "bodyMarkdown": {
            "type": "string",
            "description": "Comment body normalized from HTML to markdown."
          },
          "creationDate": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the comment was posted — the newest comments carry the freshest corrections."
          }
        },
        "description": "A single comment with markdown body, score, date, and author attribution.",
        "additionalProperties": false
      },
      "description": "Comments on the question, newest first, present only when includeComments is true. An empty array means this post has no comments; an absent array means its comment state is unknown — either comments were not requested, or the batched fetch was cut short before this post contributed any. Never read an absent array as \"no comments\"."
    },
    "quotaMax": {
      "type": "number",
      "description": "Maximum API quota calls per day (300 keyless, ~10,000 with API key)."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when answers were capped at maxAnswers."
    },
    "authorLink": {
      "type": "string",
      "description": "Question author profile URL when available."
    },
    "authorName": {
      "type": "string",
      "description": "Question author display name when available."
    },
    "questionId": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Numeric question ID — identifies this thread on the site."
    },
    "answerCount": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Total answers the question has upstream. When greater than the returned answers[] length, more answers exist — raise maxAnswers to fetch them."
    },
    "commentsCap": {
      "type": "number",
      "description": "Maximum comments carried per post — a post at this count reports commentsTruncated."
    },
    "authorUserId": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Question author numeric user ID when available — pass to stackexchange_get_user to fetch the full profile."
    },
    "bodyMarkdown": {
      "type": "string",
      "description": "Question body normalized from HTML to markdown."
    },
    "creationDate": {
      "type": "string",
      "description": "ISO 8601 timestamp of when the question was asked — use it to judge whether the advice is still current."
    },
    "siteConflict": {
      "type": "object",
      "required": [
        "resolvedBy",
        "urlHost",
        "site"
      ],
      "properties": {
        "site": {
          "type": "string",
          "description": "The site value passed."
        },
        "urlHost": {
          "type": "string",
          "description": "Host of the question URL."
        },
        "resolvedBy": {
          "enum": [
            "url_host",
            "site"
          ],
          "type": "string",
          "description": "Which one the question was read from: \"url_host\" when site was ignored in favor of the URL's own site, \"site\" when the URL host is not a Stack Exchange site and site was used instead."
        }
      },
      "description": "Present only when questionIdOrUrl is a URL and site names a different site — says which of the two the question was read from.",
      "additionalProperties": false
    },
    "quotaRemaining": {
      "type": "number",
      "description": "Remaining API quota calls for the current day."
    },
    "acceptedAnswerId": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "ID of the accepted answer when one exists."
    },
    "lastActivityDate": {
      "type": "string",
      "description": "ISO 8601 timestamp of the most recent activity on the question (edit, answer, or comment)."
    },
    "commentsTruncated": {
      "type": "boolean",
      "description": "True when the question's comments[] is a partial list — more exist upstream than were returned."
    }
  },
  "additionalProperties": false
}
stackexchange_get_thread annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true
}

Prompts

0 advertised

No prompt definitions available.

Resources

1 advertised

stackexchange-guide

Advertised by the server during the last successful anonymous check.

Find, read, and cite Stack Overflow and other Stack Exchange answers with the stackexchange_* tools — resolving site and IDs from URLs, search syntax for error messages and tags, choosing which answer to trust, vetting an author, and budgeting the daily API quota. Use when answering from Stack Exchange content, quoting an answer, or checking who wrote one.

stackexchange-guide URI
skill://stackexchange-guide/SKILL.md

MIME type: text/markdown

io.modelcontextprotocol/skills

Advertised by the server during the last successful anonymous check.

io.modelcontextprotocol/skills URI template
skill://{+path}

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
735 ms
95th percentile latency
735 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 735 ms · metadata changed · 5 tool(s), 1 resource(s), 1 resource template(s), 0 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http stackexchange-mcp-server https://stackexchange.caseyjhand.com/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add stackexchange-mcp-server --url https://stackexchange.caseyjhand.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable stackexchange-mcp-server in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "stackexchange-mcp-server": {
      "url": "https://stackexchange.caseyjhand.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "stackexchange-mcp-server": {
      "type": "streamableHttp",
      "url": "https://stackexchange.caseyjhand.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start stackexchange-mcp-server and inspect its tools.
VS Code configuration
{
  "servers": {
    "stackexchange-mcp-server": {
      "type": "http",
      "url": "https://stackexchange.caseyjhand.com/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http stackexchange-mcp-server https://stackexchange.caseyjhand.com/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://stackexchange.caseyjhand.com/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "stackexchange-mcp-server": {
      "serverUrl": "https://stackexchange.caseyjhand.com/mcp"
    }
  }
}

Let your agent find its tools

Find servers like stackexchange-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.