Skip to main content
Glama
by wei
research.md14 kB
# Research & Technical Decisions **Feature**: HackerNews MCP Server **Date**: October 12, 2025 **Status**: Complete ## Overview This document captures all technical research and decisions made during Phase 0 of the implementation planning process. All "NEEDS CLARIFICATION" items from the Technical Context have been resolved through research using Context7 MCP. ## Technology Stack Decisions ### 1. Programming Language & Runtime **Decision**: Node.js with TypeScript (strict mode) **Rationale**: - MCP TypeScript SDK (`@modelcontextprotocol/sdk`) provides comprehensive, well-documented support for building MCP servers - TypeScript strict mode enables compile-time type safety, catching errors early - Node.js provides excellent HTTP client libraries for consuming the HackerNews API - Large ecosystem of testing tools (Vitest, Jest) and type-safe HTTP clients - Strong community support and extensive examples in the MCP repository **Alternatives Considered**: - **Python SDK**: Good support but TypeScript offers better IDE integration and type safety for this use case - **Kotlin/Java**: More verbose, less common for MCP servers, smaller ecosystem - **Go**: Would require manual protocol implementation, no official SDK **Source**: MCP TypeScript SDK documentation via Context7 (`/modelcontextprotocol/typescript-sdk`) --- ### 2. MCP Transport Protocol **Decision**: stdio (Standard Input/Output) **Rationale**: - stdio is the recommended transport for local MCP servers that are spawned as child processes - Simpler setup than HTTP/SSE for end users (no port management, no network configuration) - Better security model (no exposed network ports) - Matches the user requirement: "Use stdio protocol" - MCP SDK provides `StdioServerTransport` class with full support - Standard pattern in MCP ecosystem for tool-based servers **Example from Research**: ```typescript import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; const transport = new StdioServerTransport(); await server.connect(transport); ``` **Alternatives Considered**: - **HTTP with Streamable HTTP**: Better for web-based deployments but adds complexity for local usage - **SSE (Server-Sent Events)**: Deprecated in favor of Streamable HTTP, not recommended for new projects **Source**: MCP TypeScript SDK examples showing stdio as primary local transport pattern --- ### 3. Code Quality & Formatting **Decision**: Biome for linting and formatting **Rationale**: - User explicitly requested: "Use biome for linting & formatting" - Biome is a fast, all-in-one toolchain replacing ESLint + Prettier - Zero configuration conflicts (single tool for both linting and formatting) - 10-100x faster than Prettier for large codebases - Native TypeScript support with built-in rules for correctness and style - Growing ecosystem with strong community support **Configuration Approach**: ```json { "$schema": "https://biomejs.dev/schemas/1.0.0/schema.json", "formatter": { "enabled": true, "indentStyle": "tab", "lineWidth": 100 }, "linter": { "enabled": true, "rules": { "recommended": true, "correctness": { "noUnusedVariables": "error" }, "style": { "noVar": "error", "useConst": "warn" } } }, "javascript": { "formatter": { "quoteStyle": "double", "trailingCommas": "es5" } } } ``` **Alternatives Considered**: - **ESLint + Prettier**: Traditional approach but slower and requires managing two tools - **Deno fmt + lint**: Only works with Deno runtime, not compatible with Node.js **Source**: Biome documentation via Context7 (`/biomejs/biome`) --- ### 4. Testing Framework **Decision**: Vitest with separate unit, integration, and contract tests **Rationale**: - Vitest is Vite-native and extremely fast (built on esbuild) - First-class TypeScript support without additional configuration - Jest-compatible API (easy migration path if needed) - Built-in coverage reporting with c8/istanbul - Excellent watch mode for TDD workflow - Supports ESM modules natively (important for MCP SDK) **Test Structure**: ``` tests/ ├── unit/ # Pure function tests, no I/O ├── integration/ # Tests with real HackerNews API calls └── contract/ # MCP protocol compliance tests ``` **Alternatives Considered**: - **Jest**: Slower, requires more configuration for ESM - **Node:test**: Built-in but lacks maturity and ecosystem - **Mocha + Chai**: Requires more setup, less modern **Coverage Requirements** (per Constitution): - Minimum 80% coverage overall - 100% coverage for critical paths (API request/response handling) --- ### 5. HTTP Client for HackerNews API **Decision**: Native `fetch` API (Node.js 18+) **Rationale**: - Native to Node.js 18+ (no external dependencies) - Standard web API (same interface as browser fetch) - Built-in TypeScript types - Promise-based, async/await friendly - Sufficient for HackerNews API needs (simple GET requests) - Reduces dependency footprint (aligns with Constitution Principle V) **Example Usage**: ```typescript const response = await fetch('https://hn.algolia.com/api/v1/search?query=AI'); const data = await response.json(); ``` **Alternatives Considered**: - **axios**: Popular but adds 450KB+ of dependencies, unnecessary for simple GET requests - **got**: Powerful but heavyweight, better for complex scenarios - **node-fetch**: No longer needed with Node 18+ built-in fetch **Dependency Minimization**: Using native fetch eliminates an entire dependency category --- ### 6. Schema Validation **Decision**: Zod for runtime schema validation **Rationale**: - MCP SDK uses Zod extensively for tool input/output schemas - TypeScript-first design provides excellent type inference - Composable schema definitions with clear error messages - Small bundle size (~8KB minified + gzipped) - Active development and strong community - Built-in validation for API responses and tool inputs **Example from MCP SDK**: ```typescript server.registerTool( 'search-posts', { inputSchema: { query: z.string().min(1), tags: z.array(z.string()).optional(), page: z.number().int().min(0).default(0) }, outputSchema: { hits: z.array(z.any()), nbHits: z.number() } }, async (params) => { /* handler */ } ); ``` **Alternatives Considered**: - **io-ts**: More functional but steeper learning curve - **Yup**: Object-oriented but less TypeScript-native - **JSON Schema**: Verbose, less ergonomic for TypeScript **Source**: MCP SDK examples showing Zod as standard for schema definition --- ### 7. Project Structure **Decision**: Modular tool-based structure with separate files per tool **Rationale**: - User requirement: "structured the app so tool calls are separated by file" - Promotes single responsibility principle (Constitution I) - Easier testing (each tool can be tested in isolation) - Better code organization and maintainability - Follows MCP best practices from examples **Structure**: ``` src/ ├── index.ts # Main entry point, server setup ├── tools/ # MCP tool implementations │ ├── search-posts.ts # Search tool │ ├── get-front-page.ts # Front page tool │ ├── get-latest-posts.ts # Latest posts tool │ ├── get-item.ts # Item retrieval tool │ └── get-user.ts # User profile tool ├── services/ # Business logic │ └── hn-api.ts # HackerNews API client ├── types/ # TypeScript type definitions │ ├── hn-types.ts # HackerNews API response types │ └── mcp-types.ts # MCP-specific types └── utils/ # Shared utilities ├── validators.ts # Input validation helpers └── error-handlers.ts # Error handling utilities ``` **Benefits**: - Clear separation of concerns - Easy to locate and modify specific tools - Supports incremental development (build one tool at a time) - Facilitates parallel development by multiple contributors --- ### 8. Error Handling Strategy **Decision**: Structured error handling with typed error responses **Rationale**: - MCP protocol supports `isError` flag in tool responses - TypeScript enables type-safe error handling - Clear error messages improve user experience (Constitution III) - All errors must be explicitly handled (Constitution I) **Pattern**: ```typescript try { const response = await fetch(url); if (!response.ok) { return { content: [{ type: 'text', text: `API error: ${response.statusText}` }], isError: true }; } // ... process response } catch (error) { return { content: [{ type: 'text', text: `Network error: ${error.message}` }], isError: true }; } ``` --- ### 9. Rate Limiting Strategy **Decision**: Informational warnings, no automatic throttling **Rationale**: - HackerNews API rate limit: 10,000 requests/hour per IP - For typical MCP usage, this limit is unlikely to be hit - Adding throttling adds complexity without clear benefit - Better to fail fast with clear error messages - Can be added later if usage patterns warrant it **Implementation**: - Document rate limits clearly in README - Return helpful error messages when 429 status received - Include rate limit info in tool descriptions --- ### 10. Documentation Approach **Decision**: Multi-tier documentation for different audiences **Rationale**: - User requirement: "create a user-facing readme and documentation suitable for open source distribution and collaboration" - Constitution Principle IV: Documentation-First Development **Documentation Structure**: 1. **README.md**: Quick start, installation, basic usage examples 2. **docs/API.md**: Detailed API reference for all tools 3. **docs/CONTRIBUTING.md**: Development setup, testing, contribution guidelines 4. **docs/ARCHITECTURE.md**: System design, component interactions 5. **Inline JSDoc**: For all public functions and types **Target Audiences**: - **End Users**: README with installation and usage - **Contributors**: CONTRIBUTING and ARCHITECTURE docs - **API Consumers**: Tool descriptions in MCP tool definitions - **Developers**: JSDoc comments and type definitions --- ## Best Practices from MCP Examples ### 1. Tool Registration Pattern Based on official MCP examples, tools should: - Use clear, descriptive names (e.g., `search-posts`, not `search`) - Provide comprehensive descriptions for LLM understanding - Define precise input/output schemas with Zod - Return both `content` (for display) and `structuredContent` (for parsing) ### 2. Resource vs Tool Decision **Decision**: Use Tools only, no Resources **Rationale**: - HackerNews API is query-based (requires parameters) - Resources are for static or addressable content (e.g., `file://`, `config://`) - Tools are appropriate for API operations with inputs - Simpler mental model for users ### 3. Prompts **Decision**: No custom prompts initially **Rationale**: - Prompts are useful for pre-defined queries or templates - HackerNews queries are too variable to template effectively - Can be added in future if common patterns emerge - Focus on core functionality first --- ## Performance Targets Based on success criteria from spec.md: | Operation | Target | Rationale | |-----------|--------|-----------| | Search queries | < 2 seconds | Matches user expectation (SC-001) | | Front page retrieval | < 2 seconds | Simple API call, should be fast | | Item retrieval | < 3 seconds | May need nested comments (SC-003) | | User profile | < 1 second | Simple API endpoint (SC-004) | **Implementation Notes**: - No client-side caching initially (per out-of-scope) - Performance primarily depends on HackerNews API response times - Connection reuse via keep-alive headers - Timeouts set to 5 seconds to fail fast --- ## Security Considerations 1. **No Authentication Required**: HackerNews API is public and read-only 2. **Input Validation**: All user inputs validated with Zod schemas 3. **Error Message Safety**: Never expose internal stack traces to users 4. **Dependency Security**: Regular security audits with `npm audit` 5. **Rate Limiting**: Respect API limits, clear error messages on violations --- ## Development Workflow **Test-First Development** (Constitution Principle II): 1. Write failing test for tool behavior 2. Implement minimum code to pass test 3. Refactor with tests passing 4. Repeat for next feature **Git Workflow**: - Feature branch: `001-hackernews-mcp-server` - Commit convention: `type(scope): description` - PR reviews required before merge --- ## Open Questions & Future Considerations ### Potential Enhancements (Not in MVP): 1. **Caching Layer**: Could add in-memory cache for frequently accessed items 2. **Batch Operations**: Could support fetching multiple items in one call 3. **Subscription Support**: Real-time updates for front page changes 4. **Advanced Filtering**: Client-side filtering beyond API capabilities ### Monitoring Considerations: - Request success/failure metrics - Response time tracking - Error rate monitoring - Usage patterns analysis These are explicitly out of scope for initial implementation but documented for future reference. --- ## Summary All technical unknowns have been resolved: ✅ **Language/Runtime**: Node.js + TypeScript (strict mode) ✅ **Transport**: stdio protocol via `StdioServerTransport` ✅ **Testing**: Vitest with 80%+ coverage target ✅ **Linting/Formatting**: Biome (per user request) ✅ **HTTP Client**: Native fetch API (Node 18+) ✅ **Validation**: Zod schemas (MCP standard) ✅ **Structure**: Modular tool-per-file organization ✅ **Error Handling**: Typed errors with MCP `isError` flag ✅ **Documentation**: Multi-tier for different audiences **Next Phase**: Design data models and API contracts based on these decisions.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wei/hn-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server