Skip to main content
Glama
charlielockyer-rice

tscircuit MCP Server

server.ts6.15 kB
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; import { readFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import TscircuitAPI from './tscircuit-api.js'; import { ComponentCategory } from './types.js'; export class TscircuitMCPServer { private server: McpServer; private api: TscircuitAPI; constructor() { this.server = new McpServer({ name: 'tscircuit-mcp', version: '1.0.0', }); this.api = new TscircuitAPI(); this.setupHandlers(); } private setupHandlers(): void { // Register resources this.server.resource( 'ai-context', 'tscircuit://ai-context', { description: 'AI context for working with tscircuit - comprehensive documentation and usage patterns' }, async (uri: URL) => { try { const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const aiContextPath = join(__dirname, '..', 'docs', 'ai.txt'); const aiContext = readFileSync(aiContextPath, 'utf8'); return { contents: [{ uri: uri.toString(), mimeType: 'text/plain', text: aiContext, }], }; } catch (error) { throw new Error(`Failed to load AI context: ${error instanceof Error ? error.message : 'Unknown error'}`); } } ); this.server.resource( 'search', 'tscircuit://packages/search', { description: 'Search for tscircuit packages' }, async (uri: URL) => { const query = uri.searchParams.get('q') || ''; const limit = parseInt(uri.searchParams.get('limit') || '10'); const category = uri.searchParams.get('category') || undefined; if (!query) { throw new Error('Search query parameter "q" is required'); } const results = await this.api.searchPackages({ query, limit, category }); return { contents: [{ uri: uri.toString(), mimeType: 'application/json', text: JSON.stringify(results, null, 2), }], }; } ); this.server.resource( 'package-details', new ResourceTemplate('tscircuit://packages/{packageName}', { list: undefined, }), { description: 'Get detailed information about a tscircuit package' }, async (uri: URL, variables: any) => { const packageName = variables.packageName; const details = await this.api.getPackageDetails({ packageName }); return { contents: [{ uri: uri.toString(), mimeType: 'application/json', text: JSON.stringify(details, null, 2), }], }; } ); this.server.resource( 'package-code', new ResourceTemplate('tscircuit://packages/{packageName}/code', { list: undefined, }), { description: 'Get the source code for a tscircuit package' }, async (uri: URL, variables: any) => { const packageName = variables.packageName; const version = uri.searchParams.get('version') || undefined; const code = await this.api.getPackageCode({ packageName, version }); return { contents: [{ uri: uri.toString(), mimeType: 'text/plain', text: code, }], }; } ); // Register tools this.server.tool( 'search_components', 'Search for electronic components in the tscircuit registry', { query: z.string().describe('Search terms (component name, type, description)'), limit: z.number().optional().default(10).describe('Maximum results to return'), category: z.enum([ 'resistor', 'capacitor', 'inductor', 'diode', 'transistor', 'ic', 'connector', 'led', 'switch', 'sensor', 'crystal', 'relay', 'transformer', 'fuse', 'battery', 'motor', 'display', 'antenna', 'other' ]).optional().describe('Filter by component category'), }, async (args) => { const results = await this.api.searchPackages(args); return { content: [{ type: 'text', text: JSON.stringify(results, null, 2), }], }; } ); this.server.tool( 'get_package_details', 'Get detailed information about a specific tscircuit package', { packageName: z.string().describe('Full package name (e.g., "seveibar/red-led")'), }, async (args) => { const details = await this.api.getPackageDetails(args); return { content: [{ type: 'text', text: JSON.stringify(details, null, 2), }], }; } ); this.server.tool( 'get_package_code', 'Retrieve the source code for a tscircuit component', { packageName: z.string().describe('Package name'), version: z.string().optional().describe('Specific version (defaults to latest)'), }, async (args) => { const code = await this.api.getPackageCode(args); return { content: [{ type: 'text', text: code, }], }; } ); this.server.tool( 'analyze_component', 'Analyze a component\'s electrical specifications and footprint', { packageName: z.string().describe('Package to analyze'), }, async (args) => { const analysis = await this.api.analyzeComponent(args); return { content: [{ type: 'text', text: JSON.stringify(analysis, null, 2), }], }; } ); } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); } getServer(): McpServer { return this.server; } getAPI(): TscircuitAPI { return this.api; } }

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/charlielockyer-rice/tscircuit-mcp'

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