search_rfcs
Find relevant IETF RFC documents by entering search keywords. Specify a result limit to refine the output and access programmatic data extraction from RFC MCP Server.
Instructions
Search for RFCs by keyword
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results to return | |
| query | Yes | Search keyword or phrase |
Implementation Reference
- src/services/rfcService.ts:72-153 (handler)Core handler function implementing the search_rfcs tool logic. Scrapes the RFC Editor search page, parses the HTML results table, and extracts metadata for matching RFCs.async searchRfcs(keyword: string): Promise<RfcMetadata[]> { try { // Search on the RFC Editor website const searchUrl = `https://www.rfc-editor.org/search/rfc_search_detail.php?title=${encodeURIComponent(keyword)}&pubstatus%5B%5D=Any&pub_date_type=any`; const response = await axios.get(searchUrl); const dom = new JSDOM(response.data); const document = dom.window.document; // Extract search results const results: RfcMetadata[] = []; // The results are in a table with class 'gridtable' const resultsTable = document.querySelector('table.gridtable'); if (!resultsTable) { // If we can't find the gridtable, look for any table after the results count const resultNodes = Array.from(document.querySelectorAll('p')).filter( node => node.textContent?.includes('results') && /\d+\s+results/.test(node.textContent) ); if (resultNodes.length === 0) return results; } // Get all rows from the results table const rows = resultsTable?.querySelectorAll('tr'); if (!rows || rows.length <= 1) return results; // Skip the header row for (let i = 1; i < rows.length; i++) { const row = rows[i]; const cells = row.querySelectorAll('td'); if (cells.length >= 5) { // Extract RFC number from first column const rfcLinkElement = cells[0].querySelector('a'); if (!rfcLinkElement) continue; // Get RFC number from text content let rfcNumber = ''; const rfcTextContent = rfcLinkElement.textContent?.trim() || ''; const rfcMatch = rfcTextContent.match(/RFC\s*(\d+)/i); if (rfcMatch && rfcMatch[1]) { rfcNumber = rfcMatch[1]; } if (!rfcNumber) continue; // Title is in the third column const title = cells[2].textContent?.trim() || ''; // Authors are in the fourth column const authorsText = cells[3].textContent?.trim() || ''; const authors = authorsText ? [authorsText] : []; // Date is in the fifth column const date = cells[4].textContent?.trim() || ''; // Status is in the seventh column const status = cells[6]?.textContent?.trim() || ''; // Get URL from the link in the first column const url = rfcLinkElement.getAttribute('href') || `https://www.rfc-editor.org/info/rfc${rfcNumber}`; results.push({ number: rfcNumber, title, authors, date, status, abstract: '', // Would need to fetch the full RFC to get this url }); } } return results; } catch (error) { console.error('Error in searchRfcs:', error); return []; // Return empty array instead of throwing } }
- src/services/rfcService.ts:4-11 (schema)Type definition for the output of the search_rfcs tool (RfcMetadata array).interface RfcMetadata { number: string; title: string; authors: string[]; date: string; status: string; abstract: string; url: string;
- src/index.ts:150-165 (schema)Input schema validation for the search_rfcs tool.inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search keyword or phrase', }, limit: { type: 'number', description: 'Maximum number of results to return', default: 10, }, }, required: ['query'], additionalProperties: false, },
- src/index.ts:147-166 (registration)Registration of the search_rfcs tool in the MCP ListTools response.{ name: 'search_rfcs', description: 'Search for RFCs by keyword', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search keyword or phrase', }, limit: { type: 'number', description: 'Maximum number of results to return', default: 10, }, }, required: ['query'], additionalProperties: false, }, },
- src/index.ts:246-279 (handler)MCP tool dispatcher/handler for search_rfcs: validates input, applies limit, calls service implementation, and formats response.case 'search_rfcs': { if (typeof typedArgs.query !== 'string') { throw new McpError( ErrorCode.InvalidParams, 'Search query must be a string' ); } const limit = typeof typedArgs.limit === 'number' ? typedArgs.limit : 10; try { const results = await rfcService.searchRfcs(typedArgs.query); const limitedResults = results.slice(0, limit); return { content: [ { type: 'text', text: JSON.stringify(limitedResults, null, 2), }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error searching for RFCs: ${error}`, }, ], isError: true, }; } }