Skip to main content
Glama
SuReaper

NullShot Typescript MCP Template

by SuReaper
server.ts9.97 kB
import { Implementation } from '@modelcontextprotocol/sdk/types.js'; import { McpHonoServerDO } from '@nullshot/mcp'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; const CORTENSOR_ROUTER = 'https://cortensor.app'; async function cortensorInfer(prompt: string, timeout = 120): Promise<string> { const response = await fetch(`${CORTENSOR_ROUTER}/api/v1/completions/0`, { method: 'POST', headers: { 'Authorization': 'Bearer default-dev-token', 'Content-Type': 'application/json', }, body: JSON.stringify({ prompt, stream: false, timeout }), }); if (!response.ok) { throw new Error(`cortensor ${response.status}`); } const data = await response.json() as { result?: string }; return data.result || JSON.stringify(data); } function formatError(tool: string, error: unknown): string { const msg = error instanceof Error ? error.message : String(error); return `[${tool}] failed: ${msg}\n\ncortensor testnet may be syncing. mcp integration is functional.`; } export class CortensorMCP extends McpHonoServerDO<Env> { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); } getImplementation(): Implementation { return { name: 'CortensorMCP', version: '1.0.0' }; } configureServer(server: McpServer): void { // pass storage reference to tools that need persistence const storage = this.ctx.storage; // session create - uses durable object storage now server.tool( 'session_create', 'Create or retrieve an agent session with persistent memory.', { session_id: z.string().optional(), initial_context: z.record(z.unknown()).optional(), }, async ({ session_id, initial_context }) => { const id = session_id || `s_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`; let session = await storage.get<{ history: string[]; context: Record<string, unknown> }>(`session:${id}`); if (!session) { session = { history: [], context: initial_context || {} }; await storage.put(`session:${id}`, session); } return { content: [{ type: 'text', text: JSON.stringify({ session_id: id, context_keys: Object.keys(session.context) }, null, 2) }] }; } ); // session remember - persists to durable storage server.tool( 'session_remember', 'Store information in session memory.', { session_id: z.string(), key: z.string(), value: z.unknown(), }, async ({ session_id, key, value }) => { const session = await storage.get<{ history: string[]; context: Record<string, unknown> }>(`session:${session_id}`); if (!session) { return { content: [{ type: 'text', text: `session ${session_id} not found` }] }; } session.context[key] = value; session.history.push(`stored:${key}`); await storage.put(`session:${session_id}`, session); return { content: [{ type: 'text', text: `stored "${key}" in session` }] }; } ); // session recall server.tool( 'session_recall', 'Retrieve stored information from session.', { session_id: z.string(), key: z.string().optional(), }, async ({ session_id, key }) => { const session = await storage.get<{ history: string[]; context: Record<string, unknown> }>(`session:${session_id}`); if (!session) { return { content: [{ type: 'text', text: `session ${session_id} not found` }] }; } const data = key ? session.context[key] : session.context; return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // task route server.tool( 'task_route', 'Route a structured task to Cortensor.', { task_type: z.enum(['analyze', 'summarize', 'extract', 'generate', 'validate', 'decide', 'plan']), input: z.string(), output_format: z.enum(['text', 'json', 'markdown', 'list']).optional(), }, async ({ task_type, input, output_format = 'text' }) => { const formats: Record<string, string> = { text: 'Respond in plain text.', json: 'Respond with valid JSON only.', markdown: 'Respond in markdown.', list: 'Respond as a numbered list.', }; const tasks: Record<string, string> = { analyze: 'Analyze thoroughly, identify patterns and insights.', summarize: 'Summarize concisely, preserve key info.', extract: 'Extract key data points and entities.', generate: 'Generate content based on requirements.', validate: 'Validate for correctness and flag issues.', decide: 'Make a reasoned decision with explanation.', plan: 'Create actionable plan with steps and priorities.', }; try { const result = await cortensorInfer(`${tasks[task_type]} ${formats[output_format]}\n\nINPUT:\n${input}`); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('task_route', error) }] }; } } ); // validate rubric server.tool( 'validate_rubric', 'Validate content against a scoring rubric.', { content: z.string(), rubric: z.array(z.object({ criterion: z.string(), weight: z.number().optional(), })), pass_threshold: z.number().optional(), }, async ({ content, rubric, pass_threshold = 70 }) => { const rubricText = rubric.map((r, i) => `${i + 1}. ${r.criterion} (weight: ${r.weight || 1})`).join('\n'); try { const result = await cortensorInfer( `Score this content against each criterion 0-100. Return JSON with scores, total_score (weighted avg), pass (true if >= ${pass_threshold}), and summary.\n\nRUBRIC:\n${rubricText}\n\nCONTENT:\n${content}` ); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('validate_rubric', error) }] }; } } ); // validate consistency server.tool( 'validate_consistency', 'Check content for contradictions and logical issues.', { content: z.string(), reference: z.string().optional(), }, async ({ content, reference }) => { const ref = reference ? `\n\nREFERENCE:\n${reference}` : ''; try { const result = await cortensorInfer( `Check for contradictions and inconsistencies. Return JSON: {consistent: bool, issues: [{type, description, severity}], summary}.${ref}\n\nCONTENT:\n${content}` ); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('validate_consistency', error) }] }; } } ); // research analyze server.tool( 'research_analyze', 'Analyze code or docs, extract issues and todos.', { content: z.string(), content_type: z.enum(['code', 'docs', 'readme', 'issue', 'changelog']), }, async ({ content, content_type }) => { try { const result = await cortensorInfer( `Analyze this ${content_type}. Return JSON with: summary, issues found, todos, and action_items prioritized.\n\nCONTENT:\n${content}` ); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('research_analyze', error) }] }; } } ); // research summarize server.tool( 'research_summarize', 'Generate summary report from multiple items.', { items: z.array(z.object({ title: z.string(), content: z.string(), })), report_type: z.enum(['digest', 'changelog', 'status']).optional(), }, async ({ items, report_type = 'digest' }) => { const itemsText = items.map((it, i) => `[${i + 1}] ${it.title}: ${it.content}`).join('\n'); try { const result = await cortensorInfer( `Create a ${report_type} report. Include highlights, key details, and action items.\n\nITEMS:\n${itemsText}` ); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('research_summarize', error) }] }; } } ); // cortensor status server.tool( 'cortensor_status', 'Check Cortensor network status.', {}, async () => { const checks: Record<string, unknown> = { router: CORTENSOR_ROUTER, mcp_server: 'operational', timestamp: new Date().toISOString(), }; try { const start = Date.now(); const res = await fetch(`${CORTENSOR_ROUTER}/api/v1/status`); checks['latency_ms'] = Date.now() - start; checks['network'] = res.ok ? 'online' : 'degraded'; } catch { checks['network'] = 'unreachable'; } return { content: [{ type: 'text', text: JSON.stringify(checks, null, 2) }] }; } ); // raw inference server.tool( 'cortensor_infer', 'Direct inference request to Cortensor.', { prompt: z.string(), }, async ({ prompt }) => { try { const result = await cortensorInfer(prompt); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: formatError('cortensor_infer', error) }] }; } } ); } }

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/SuReaper/cortensor-mcp'

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