Skip to content

Remove legacy SeiJS docs and migrate MCP search - #319

Open
alexander-sei wants to merge 4 commits into
mainfrom
chore/remove-legacy-docs
Open

Remove legacy SeiJS docs and migrate MCP search#319
alexander-sei wants to merge 4 commits into
mainfrom
chore/remove-legacy-docs

Conversation

@alexander-sei

@alexander-sei alexander-sei commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove the in-repo Mintlify documentation site, CLI dependency, stale links, and obsolete toolchain overrides.
  • Replace the legacy Mintlify/Trieve MCP integration with search_docs backed by the official https://docs.sei.io/mcp endpoint.
  • Update MCP documentation links and add a minor @sei-js/mcp-server changeset.

Linear

Test plan

  • pnpm build:all
  • pnpm test:all
  • Confirm a live MCP search returns content from docs.sei.io

Remove the in-repo Mintlify stack and route MCP documentation search and links through docs.sei.io.

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov-commenter

codecov-commenter commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.70330% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.55%. Comparing base (2896a13) to head (b26c003).

Files with missing lines Patch % Lines
packages/mcp-server/src/docs/server.ts 96.62% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #319      +/-   ##
==========================================
+ Coverage   79.75%   82.55%   +2.80%     
==========================================
  Files          83       79       -4     
  Lines        1309     1330      +21     
  Branches      217      225       +8     
==========================================
+ Hits         1044     1098      +54     
+ Misses        259      226      -33     
  Partials        6        6              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped migration off the in-repo Mintlify/Trieve docs stack to the official docs.sei.io MCP endpoint — the dependency-injected client makes search_docs testable and removes a startup-time network dependency, and I verified no dangling mintlify/trieve/sei-js.docs.sei.io references, no leftover asyncapi lockfile entries, and no impact on the wallet-stdio or SSE-session security invariants. No blockers; the notes concern a per-call MCP handshake, a hardcoded remote tool name, unverified passthrough of remote content, and whether docs.sei.io actually covers the @sei-js docs this PR deletes.

Findings: 0 blocking | 12 non-blocking | 6 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • Both second-opinion passes produced no output: codex-review.md and cursor-review.md are empty files, so nothing from Codex or Cursor could be merged into this review.
  • Capability regression: search_sei_js_docs (Trieve-backed, scoped to the @sei-js libraries) is removed and not replaced by a dedicated tool. MCP clients now get a single search_docs pointed at the main Sei docs. Please confirm docs.sei.io indexes the @sei-js package documentation — if it doesn't, agents lose the ability to look up @sei-js APIs entirely, which is the main functional risk in this PR.
  • Link rot / decommissioning: the repo is now clean of sei-js.docs.sei.io references (verified), but already-published npm versions of all six packages, plus any third-party links, still point at that host. Worth confirming the Mintlify project is being retired with redirects to docs.sei.io rather than left to 404. Same question for https://docs.sei.io/ai/mcp-server, the new README target — I could not verify it resolves from this environment.
  • packages/mcp-server/package.json declares @modelcontextprotocol/sdk: ^1.7.0, but client/streamableHttp.js (and the two-arg Client.connect(transport, options) overload this PR relies on) only exist in later 1.x releases. The lockfile resolves 1.17.5 so CI passes, yet a consumer whose tree resolves 1.7.x would fail at import time. This floor is already too low for the existing server/streamableHttp.js import, so it's pre-existing — but this PR adds a second dependency on the newer API and is a good moment to raise the minimum.
  • Removing pnpm.overrides for @asyncapi/* is correct as far as I can tell — those pins were transitive to the now-deleted mint CLI, and pnpm-lock.yaml contains zero asyncapi entries after the change. Flagging only because the review guidelines call out those pins as a deliberate addition; no action needed unless they were kept for an advisory unrelated to mint.
  • Test coverage for the new module is thinner than the code it replaces (which had ~10 cases). src/tests/docs/server.test.ts covers the happy path and a connect rejection, but not: callTool rejecting, a non-Error value being thrown (the String(error) branch), or client.close() throwing (the deliberately swallowed catch {}). Per the guidelines this doesn't fail a gate since mcp-server has no Codecov target, but the close()-throws branch in particular is the kind of cleanup path worth pinning.
  • 6 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts
Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread .changeset/remove-docs-integrations.md Outdated
Reuse and validate the docs MCP session, constrain remote output, and report the actual client version so search remains safe across upstream changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
MCP search_docs now depends on live docs.sei.io availability and remote tool naming; behavior change for agents that used search_sei_js_docs or local Mintlify/Trieve search.

Overview
Removes the in-repo Mintlify documentation site (docs/ MDX, docs.json, LLM text exports) and trims README references to sei-js.docs.sei.io and docs-from-build:all.

@sei-js/mcp-server (minor): Drops search_sei_js_docs and implements search_docs as a client to https://docs.sei.io/mcp (streamable HTTP), discovering the remote search_sei_docs tool, with connection reuse, timeouts, response truncation, and cleanup on server close. The compiled docs search module stays in the published package.

Docs for MCP tools/context that lived in the deleted site are removed with the site; consumers are pointed at official docs.sei.io.

Reviewed by Cursor Bugbot for commit b26c003. Bugbot is set up for automated code reviews on this repo. Configure here.

@alexander-sei

Copy link
Copy Markdown
Contributor Author

Addressed the AI review follow-ups in 39076566:

  • reuse a lazy docs MCP session and reconnect after transport/call failures
  • discover and validate the remote search tool, with an explicit contract error and fallback
  • restrict remote output to text and cap it at 40,000 characters
  • send the real package version and raise the MCP SDK floor to ^1.17.5
  • expand tests across reconnection, fallback, malformed output, truncation, and cleanup failures
  • clarify the search_sei_js_docs removal in the changeset

A live query also confirmed docs.sei.io indexes @sei-js content. Redirecting the retired public hostname is deployment/DNS work outside this repository.

Comment thread packages/mcp-server/src/docs/server.ts

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped migration: the broken docs.sei-apis.io/search backend and the Mintlify/Trieve integration are replaced with a pooled MCP client against https://docs.sei.io/mcp, dead code and the in-repo docs site are removed, and the new module has real unit tests plus a changeset. No blocking defects found; the remaining notes are resilience/verification questions around the new client lifecycle and the npm tarball.

Findings: 0 blocking | 10 non-blocking | 4 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor review file (cursor-review.md) is empty — that pass produced no output, so this review merges only Claude's findings with Codex's single P2.
  • No test exercises the real Client / StreamableHTTPClientTransport. Every case in src/tests/docs/server.test.ts injects a hand-rolled DocsMcpClientFactory, so the @modelcontextprotocol/sdk bump (^1.7.0 → ^1.17.5) and the actual connect/onclose/callTool wiring are unverified by CI. The PR description says a live search was confirmed manually; consider a smoke test (or at least noting the manual check in the changeset) since this is the exact class of breakage PLT-843 was. Per guidelines §4, mcp-server has no Codecov target, so this is on merits only.
  • Dropping the pnpm.overrides pins for @asyncapi/* reverts deliberate supply-chain hardening (per the CHANGELOGs, the vector was mint@asyncapi/parser). I verified this is safe as landed: mint is gone and pnpm-lock.yaml no longer resolves any @asyncapi/* package. Worth calling out in the PR body so the removal isn't read later as an accidental regression of that fix.
  • README changes ship in the npm tarballs for create-sei, ledger, precompiles and sei-global-wallet (all four list README.md in files), but only @sei-js/mcp-server has a changeset. Those packages will keep advertising the now-dead sei-js.docs.sei.io links on npm until an unrelated release. Per guidelines §3 this is a question, not a defect — the repo has precedent for patch changesets across all six.
  • The PR deletes ~19k lines of .mdx that backed sei-js.docs.sei.io. Confirm that host redirects to docs.sei.io (or is retired deliberately) — inbound links from published npm READMEs of already-released versions will otherwise 404 permanently.
  • Positive note, no action needed: DOCS_MCP_URL is a hardcoded HTTPS constant with no env override, unlike the *_RPC_URL overrides in core/chains.ts. Keeping it non-overridable is the right call for a surface whose text is inlined straight into the model's context.
  • 4 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts
Comment thread packages/mcp-server/.npmignore
Keep shared sessions alive across per-query failures, use the client close hook, and validate discovered tool schemas before invocation.

Co-authored-by: Cursor <cursoragent@cursor.com>
seidroid[bot]
seidroid Bot previously requested changes Aug 7, 2026

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Mintlify/Trieve removal and the search_docs rewrite onto https://docs.sei.io/mcp are clean and well-tested, with no leftover references to the deleted docs site or the dropped mint/trieve/@asyncapi deps. One blocking issue: under the stateless streamable-http transport a fresh McpServer is built per request, so each docs search opens an outbound MCP session to docs.sei.io that is never closed.

Findings: 1 blocking | 7 non-blocking | 3 posted inline

Blockers

  • None at the file/PR level.
  • 1 blocking issue(s) flagged inline on specific lines.

Non-blocking

  • The Cursor second-opinion file (cursor-review.md) is empty — that pass produced no output, so this review merges only my findings with Codex's.
  • I could not run pnpm build:all / pnpm test:all in this environment (no node_modules installed; Codex reported the same). The new src/tests/docs/server.test.ts reads as well-targeted — session reuse, reconnect-on-close, tool discovery + fallback, non-text filtering, truncation, and cleanup-failure paths are all covered — but the suite is unverified here. Per the guidelines mcp-server has no Codecov target, so this is a note, not a gate.
  • @modelcontextprotocol/sdk jumps ^1.7.0^1.17.5, a large minor range on the package that also backs stdio.ts, http-sse.ts, and streamable-http.ts. None of those files change here; worth confirming the existing http-sse session-isolation tests still pass against the new SDK before merging.
  • The PR deletes the entire in-repo @sei-js docs site and the search_sei_js_docs tool, and the new search_docs description claims coverage of "@sei-js references". Worth confirming that the per-package content (precompiles, ledger, sei-global-wallet, create-sei, x402) actually landed on docs.sei.io and is indexed by its MCP endpoint — otherwise this is a net capability loss for the tool, not just a backend swap. The package READMEs now point only at GitHub/NPM, so there is no fallback.
  • A changeset is present (.changeset/remove-docs-integrations.md, minor for @sei-js/mcp-server), which satisfies guideline 3. The root package.json change (dropping the docs script, mint, and the @asyncapi pnpm.overrides) is build-tooling only and @asyncapi no longer appears in pnpm-lock.yaml, so no additional changeset is needed there.
  • 2 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread packages/mcp-server/src/docs/server.ts Outdated
Comment thread packages/mcp-server/src/docs/server.ts
Comment thread packages/mcp-server/src/docs/server.ts Outdated
Tie outbound docs clients to the local server lifecycle and recover expired remote sessions without disrupting ordinary query failures.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b26c003. Configure here.

} catch (error) {
if (client && error instanceof StreamableHTTPError && (error.code === 404 || error.code === 410)) {
await closeClient(client);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Session recovery never triggers

Medium Severity

The new session-expiry recovery closes the pooled docs client only when callTool/listTools rejects with StreamableHTTPError and status 404/410. The lockfile pins @modelcontextprotocol/sdk@1.17.5, where streamable HTTP send() rejects with a plain Error for non-OK responses (no .code), so instanceof StreamableHTTPError stays false. After a remote session expires, the stale client remains cached and later search_docs calls keep failing until process restart.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b26c003. Configure here.

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid, well-tested migration: the .npmignore docs/ removal is the genuine root-cause fix for the broken search_docs tool, and dropping the @asyncapi overrides is safe because mint was the only path to @asyncapi/parser (lockfile removes 14 asyncapi lines, adds none). No blockers; a few resilience nits in the new docs MCP client and some docs-migration follow-ups worth confirming.

Findings: 0 blocking | 11 non-blocking | 4 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor second-opinion pass produced no output (cursor-review.md is empty), so that lens contributed nothing to this review. Codex reported no material issues.
  • Per-request session churn on streamable-http: StreamableHttpTransport calls getServer() for every POST (stateless design) and mcpServer.close() on response close, so each search_docs invocation now costs a fresh connect + listTools + callTool against docs.sei.io — three round trips where the old implementation did a single fetch. Fine for stdio (the connection is reused for the process lifetime), but worth knowing before recommending the HTTP transports for docs-heavy workloads. Caching the discovered tool name at module scope, or hoisting the docs client out of the per-request server, would cut it back to one.
  • docs/contributing.mdx was the only contributor setup/PR guide in the repo and there is no root CONTRIBUTING.md to replace it. After this PR a new contributor has no in-repo instructions for local setup or the PR process. Worth adding a short root CONTRIBUTING.md or pointing at wherever that content now lives on docs.sei.io.
  • Changeset scope: the changeset covers @sei-js/mcp-server only, but the published READMEs of create-sei, ledger, precompiles, and sei-global-wallet also changed (README is in each package's files). Those stale sei-js.docs.sei.io links stay live on npm until each package's next unrelated release. Per the repo guidelines this is a question rather than a defect — the repo has precedent for patch changesets across all six packages for release-note visibility (the @asyncapi pinning), so consider the same here.
  • Already-published npm READMEs and the wider web link to sei-js.docs.sei.io/*. Removing the source site here doesn't take down the deployment — please confirm the Mintlify project is decommissioned with redirects to the matching docs.sei.io pages, otherwise those links rot rather than move.
  • Informational, not a regression: search_docs pipes docs.sei.io content verbatim into the model's context, so that endpoint is a prompt-injection surface. The new code actually narrows it versus the old Trieve path — non-text blocks are dropped, structuredContent is discarded, and output is capped at 40k chars. No change requested; noting it so the mitigation is deliberate rather than incidental.
  • Verified and looks right: .npmignore's docs/ pattern was excluding dist/**/docs/ from the tarball (a files allowlist does not override .npmignore inside included directories), which is why the shipped search_docs was broken. Removing @asyncapi from pnpm.overrides is also safe — mint was the only route to @asyncapi/parser and the lockfile now has zero asyncapi entries. Note that pnpm build:all / pnpm test:all could not be re-run in this checkout (dependencies not installed), so the test plan is taken at the author's word.
  • 4 suggestion(s)/nit(s) flagged inline on specific lines.


return sanitizeSearchResult(result);
} catch (error) {
if (client && error instanceof StreamableHTTPError && (error.code === 404 || error.code === 410)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] The cached client is only invalidated on StreamableHTTPError with code 404/410. Any other transport-level death — ECONNRESET, TLS failure, the remote process restarting behind a load balancer — leaves the broken client memoized in clientPromise, and every subsequent search_docs call fails for the lifetime of the process. StreamableHTTPClientTransport routes request failures through onerror, not onclose, so the onclose hook on line 97 doesn't reliably cover this.

The old implementation had no such state: each call was a fresh fetch, so a transient outage self-healed on the next query. The test keeps the shared session available after an individual tool failure shows you deliberately don't want to tear down the session for one bad query, which is reasonable — but that case is a tool-level error (the remote responded), which is distinguishable from a connection-level one. Consider also invalidating when the error isn't a well-formed remote tool error.

Separately, even in the handled 404/410 path the user still gets an error for the query that triggered the reconnect. One transparent retry after closeClient would turn a visible failure into a no-op for the caller.

const properties = tool.inputSchema.properties;
return properties !== undefined && 'query' in properties;
};
const preferred = tools.find((tool) => tool.name === PREFERRED_REMOTE_DOCS_SEARCH_TOOL && acceptsQuery(tool));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] PREFERRED_REMOTE_DOCS_SEARCH_TOOL reads as though there's a fallback, but there isn't — if search_sei_docs isn't advertised under exactly that name, search_docs hard-fails. That's a deliberate choice (the does not dispatch queries to a renamed lookalike tool test pins it, and refusing to guess at an arbitrary remote tool is the safe default), so this is naming only: REQUIRED_ or EXPECTED_ would signal the actual behaviour.

Worth flagging the coupling regardless: a rename on the docs.sei.io side silently breaks docs search for every installed copy of this package, and the failure only surfaces at call time. An alert or contract test against the live endpoint would catch that before users do.

};

const selectRemoteSearchTool = async (client: DocsMcpClient): Promise<string> => {
const { tools } = await client.listTools(undefined, { timeout: CONNECT_TIMEOUT_MS });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] CONNECT_TIMEOUT_MS is used as the listTools timeout here. It works, but the name says otherwise — tool discovery is a separate round trip from the handshake and may warrant a different budget. A DISCOVERY_TIMEOUT_MS constant (even if initially the same 10s) would keep the two independently tunable.


const safeText =
text.length > MAX_DOCS_RESPONSE_CHARS
? `${text.slice(0, MAX_DOCS_RESPONSE_CHARS - TRUNCATION_NOTICE.length)}${TRUNCATION_NOTICE}`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] text.slice() cuts at a UTF-16 code-unit boundary, so a doc page containing an emoji or other astral-plane character right at the 40k mark can leave a lone surrogate at the seam. Harmless for the model, but it can trip strict UTF-8 encoders downstream. Trimming back to the last whitespace boundary would sidestep it and read better in the truncated output.

@seidroid
seidroid Bot dismissed their stale review August 7, 2026 13:48

Superseded: latest AI review found no blocking issues.

@alexander-sei
alexander-sei requested a review from monty-sei August 7, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants