-
Notifications
You must be signed in to change notification settings - Fork 51
Add main docs MCP search #269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@sei-js/mcp-server": patch | ||
| --- | ||
|
|
||
| Added main docs search tool |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { createDocsSearchTool } from './server.js'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; | ||
| import { z } from 'zod'; | ||
| import type { SeiSearchResponse } from '../mintlify/types'; | ||
|
|
||
| const DOCS_SEARCH_URL = 'https://docs.sei-apis.io/search'; | ||
|
|
||
| export const createDocsSearchTool = async (server: McpServer) => { | ||
| server.tool( | ||
| 'search_docs', | ||
| 'Search the main Sei docs for general chain information, ecosystem providers, and user onboarding guides. Useful for all queries for up-to-date information about Sei.', | ||
| { | ||
| query: z.string() | ||
| }, | ||
| async ({ query }) => { | ||
| try { | ||
| const results = await searchDocs(query); | ||
| const content = results.map((result) => { | ||
| const { title, content, link } = result; | ||
| const text = `Title: ${title}\nContent: ${content}\nLink: ${link}`; | ||
| return { | ||
| type: 'text' as const, | ||
| text | ||
| }; | ||
| }); | ||
| return { | ||
| content | ||
| }; | ||
| } catch (error) { | ||
| return { | ||
| content: [ | ||
| { | ||
| type: 'text', | ||
| text: `Error searching docs: ${error instanceof Error ? error.message : String(error)}` | ||
| } | ||
| ], | ||
| isError: true | ||
| }; | ||
| } | ||
| } | ||
| ); | ||
| }; | ||
|
|
||
| const searchDocs = async (query: string): Promise<SeiSearchResponse[]> => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this isn't necessarily a search - would call this fetchDocs or something else |
||
| const url = `${DOCS_SEARCH_URL}?q=${encodeURIComponent(query)}`; | ||
|
|
||
| try { | ||
| const response = await fetch(url); | ||
|
|
||
| if (!response.ok) { | ||
| throw new Error(`HTTP error! status: ${response.status}`); | ||
| } | ||
|
|
||
| const data = await response.json() as SeiSearchResponse[]; | ||
|
|
||
| if (!data || data.length === 0) { | ||
| throw new Error('No results found'); | ||
| } | ||
|
|
||
| return data; | ||
| } catch (error) { | ||
| if (error instanceof Error) { | ||
| throw new Error(`Search failed: ${error.message}`); | ||
| } | ||
|
|
||
| throw error; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ import { TrieveSDK } from 'trieve-ts-sdk'; | |
| import { z } from 'zod'; | ||
|
|
||
| import { DEFAULT_BASE_URL, SERVER_URL, SUBDOMAIN } from './config.js'; | ||
| import type { MintlifySearchConfig, SeiJSSearchResult, TrieveResponse, TrieveSearchResult } from './types.js'; | ||
| import type { MintlifySearchConfig, SeiSearchResponse, TrieveResponse, TrieveSearchResult } from './types.js'; | ||
| import { formatErr, throwOnAxiosError } from './utils.js'; | ||
|
|
||
| /** | ||
|
|
@@ -28,7 +28,7 @@ const fetchMintlifyConfig = async (subdomain: string): Promise<MintlifySearchCon | |
| /** | ||
| * Search Sei-JS documentation using Mintlify/Trieve API | ||
| */ | ||
| const searchSeiJSDocs = async (query: string, config: MintlifySearchConfig): Promise<SeiJSSearchResult[]> => { | ||
| const searchSeiJSDocs = async (query: string, config: MintlifySearchConfig): Promise<SeiSearchResponse[]> => { | ||
| const trieve = new TrieveSDK({ | ||
| apiKey: config.trieveApiKey, | ||
| datasetId: config.trieveDatasetId, | ||
|
|
@@ -65,7 +65,7 @@ export const createSeiJSDocsSearchTool = async (server: McpServer): Promise<void | |
|
|
||
| server.tool( | ||
| 'search_sei_js_docs', | ||
| 'Search all @sei-js libraries documentation for blockchain development, EVM/Ethereum integration, global wallet connections, React next.js and vite boilerplates, ledger integration, and the Sei chain registry', | ||
| 'Search all @sei-js libraries documentation for blockchain development, EVM/Ethereum integration, global wallet connections, React Next.js and Vite boilerplates, ledger integration, and the Sei chain registry. Useful for NodeJS based integrations with Sei.', | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| { | ||
| query: z.string() | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,10 @@ | ||
| import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; | ||
| import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; | ||
| import { getSupportedNetworks } from '../core/chains.js'; | ||
| import { registerEVMPrompts } from '../core/prompts.js'; | ||
| import { registerEVMResources } from '../core/resources.js'; | ||
| import { registerEVMTools } from '../core/tools.js'; | ||
| import { createSeiJSDocsSearchTool } from '../mintlify/index.js'; | ||
| import { createDocsSearchTool } from '../docs/index.js'; | ||
|
|
||
| // Create and start the MCP server | ||
| async function startServer() { | ||
|
|
@@ -20,7 +20,8 @@ async function startServer() { | |
| registerEVMTools(server); | ||
| registerEVMPrompts(server); | ||
|
|
||
| // Register documentation search tool | ||
| // Register documentation search tools | ||
| await createDocsSearchTool(server); | ||
| await createSeiJSDocsSearchTool(server); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now, whats the diff between Docs and SeiJSDocs ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docs come from a different source since the main docs don't use mintlify |
||
|
|
||
| // Log server information | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -150,6 +150,31 @@ describe('Balance Service', () => { | |
| // Restore console.error | ||
| console.error = originalConsoleError; | ||
| }); | ||
|
|
||
| test('should return false if there is a non-Error object thrown', async () => { | ||
| // Import mocked modules | ||
| const { readContract } = await import('../../../core/services/contracts.js'); | ||
| const { utils } = await import('../../../core/services/utils.js'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can we do anything about the relative imports? |
||
|
|
||
| // Configure mocks for this test | ||
| (readContract as jest.Mock).mockImplementation(() => { | ||
| throw 'String error message'; // Non-Error object | ||
| }); | ||
| (utils.validateAddress as jest.Mock).mockImplementation((address) => address as `0x${string}`); | ||
|
|
||
| // Mock console.error to avoid cluttering test output | ||
| const originalConsoleError = console.error; | ||
| console.error = () => {}; | ||
|
|
||
| // Call the function | ||
| const result = await isNFTOwner(VALID_TOKEN_ADDRESS, VALID_OWNER_ADDRESS, 1n); | ||
|
|
||
| // Verify results | ||
| expect(result).toBe(false); | ||
|
|
||
| // Restore console.error | ||
| console.error = originalConsoleError; | ||
| }); | ||
| }); | ||
|
|
||
| describe('getERC721Balance', () => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would now make this 20+ until you add one more