Team Ai
Datasetpublic

Brunobkr/llama.cpp_AlgMor24_github

ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes3.1kdownloads
README.md1524 linesDownload Raw Back to tmcp
1> [!WARNING]2> Unfortunately i published the 1.0 by mistake...this package is currently under heavy development so there will be breaking changes in minors...threat this `1.x` as the `0.x` of any other package. Sorry for the disservice, every breaking will be properly labeled in the PR name.3 4# tmcp5 6A lightweight, schema-agnostic Model Context Protocol (MCP) server implementation with unified API design.7 8## Why tmcp?9 10tmcp offers significant advantages over the official MCP SDK:11 12- **🔄 Schema Agnostic**: Works with any validation library through adapters13- **📦 No Weird Dependencies**: Minimal footprint with only essential dependencies (looking at you `express`)14- **🎯 Unified API**: Consistent, intuitive interface across all MCP capabilities15- **🔌 Extensible**: Easy to add support for new schema libraries16- **⚡ Lightweight**: No bloat, just what you need17 18## Supported Schema Libraries19 20tmcp works with all major schema validation libraries through its adapter system:21 22- **Zod** - `@tmcp/adapter-zod`23- **Valibot** - `@tmcp/adapter-valibot`24- **ArkType** - `@tmcp/adapter-arktype`25- **Effect Schema** - `@tmcp/adapter-effect`26- **Zod v3** - `@tmcp/adapter-zod-v3`27 28## Installation29 30```bash31pnpm install tmcp32# Choose your preferred schema library adapter33pnpm install @tmcp/adapter-zod zod34```35 36## Quick Start37 38```javascript39import { McpServer } from 'tmcp';40import { ZodJsonSchemaAdapter } from '@tmcp/adapter-zod';41import { z } from 'zod';42 43const adapter = new ZodJsonSchemaAdapter();44const server = new McpServer(45	{46		name: 'my-server',47		version: '1.0.0',48		description: 'My awesome MCP server',49	},50	{51		adapter,52		capabilities: {53			tools: { listChanged: true },54			prompts: { listChanged: true },55			resources: { listChanged: true },56		},57	},58);59 60// While the adapter is optional (you can opt out by explicitly passing `adapter: undefined`)61// without an adapter the server cannot accept inputs, produce structured outputs, or request62// elicitations at all only do this for very simple servers.63 64// Define a tool with type-safe schema65server.tool(66	{67		name: 'calculate',68		description: 'Perform mathematical calculations',69		schema: z.object({70			operation: z.enum(['add', 'subtract', 'multiply', 'divide']),71			a: z.number(),72			b: z.number(),73		}),74	},75	async ({ operation, a, b }) => {76		switch (operation) {77			case 'add':78				return {79					content: [{ type: 'text', text: `${a} + ${b} = ${a + b}` }],80				};81			case 'subtract':82				return {83					content: [{ type: 'text', text: `${a} - ${b} = ${a - b}` }],84				};85			case 'multiply':86				return {87					content: [{ type: 'text', text: `${a} × ${b} = ${a * b}` }],88				};89			case 'divide':90				return {91					content: [{ type: 'text', text: `${a} ÷ ${b} = ${a / b}` }],92				};93		}94	},95);96 97// Process incoming requests98server.receive(request);99```100 101## Return helpers to skip boilerplate102 103Even the tiny calculator tool above ends with four near-identical `return { content: [{ type: 'text', text: ... }] }` blocks. Most MCP handlers have to build the same shapes: `CallToolResult`, `ReadResourceResult`, `GetPromptResult`, or `CompleteResult`. Writing them by hand is repetitive boilerplate. The `tmcp/utils` entry point ships a handful of factories that emit the correct shape for you.104 105```ts106import { tool, resource, prompt, complete } from 'tmcp/utils';107 108// Without helpers – lots of envelope noise109server.tool(110	{ name: 'health-check', description: 'A health check tool' },111	async () => ({112		content: [{ type: 'text', text: 'ok' }],113	}),114);115 116// With helpers – just describe the payload once117server.tool(118	{ name: 'health-check', description: 'A health check tool' },119	async () => tool.text('ok'),120);121 122server.tool(123	{ name: 'profile-picture', description: 'Your profile picture' },124	async () => tool.media('image', await loadPng(), 'image/png'),125);126 127server.tool(128	{129		name: 'get-images',130		description:131			'Get the orders details and the images of all the products',132		schema: v.object({133			items: v.array(ItemsSchema),134		}),135	},136	async () => {137		const orders = await loadOrders();138		const images = await loadImages(orders);139 140		return tool.mix(141			[142				tool.text("Here's your images"),143				...images.map((img) => tool.media('image', img)),144			],145			orders,146		);147	},148);149 150server.resource(151	{152		name: 'readme',153		description: 'Top-level README',154		uri: 'file://README.md',155	},156	async (uri) =>157		resource.text(uri, await readFile(uri, 'utf8'), 'text/markdown'),158);159 160server.prompt(161	{162		name: 'explain',163		description: '',164		schema: v.object({ topic: v.string() }),165	},166	async ({ topic }) => prompt.message(`Explain ${topic} like I am five.`),167);168 169server.template(170	{171		name: 'users',172		description: 'Supports completion',173		uri: 'users/{id}',174		complete: {175			id: async (arg) =>176				complete.values(await findMatchingIds(arg), false),177		},178	},179	async (uri) => resource.blob(uri, await fetchUserBlob(uri)),180);181```182 183you can also compose different kind of tools with `tool.mix`184 185```ts186tool.mix([187	tool.text('Indexed workspace'),188	tool.media('image', png, 'image/png'),189]);190```191 192however be aware that193 1941. you can't pass `tool.structured` to `tool.mix` (but you can pass a second argument that will be the structured content)1952. if you pass even one `tool.error` to the `tool.mix` the whole return value will be an error196 197```ts198const structuredContent = {199	cool: true,200};201 202tool.mix(203	[204		tool.text(JSON.stringify(structuredContent)),205		tool.media('image', png, 'image/png'),206	],207	structuredContent,208);209```210 211### Helper catalog212 213- `tool` – build `CallToolResult` objects via `text`, `error`, `media`, `resource`, `resourceLink`, `structured`, and `mix` (merge multiple kind of tool response).214- `resource` – return `ReadResourceResult` through `text`, `blob`, or `mix` (merge `resource.text` and `resource.blob`).215- `prompt` – generate `GetPromptResult` using `message` (single string), `messages` (array of strings), `text`, `media`, `resource`, `resourceLink` and `mix` (merge multiple kind of tool response).216- `complete` – create `CompleteResult` payloads with `values(list, hasMore?, total?)`.217 218All helpers are typed, so TypeScript will prevent you from returning malformed payloads while cutting down the repetitive envelopes that used to appear in almost every handler.219 220## Defining Tools, Prompts, Resources, and Templates in Separate Files221 222For better code organization and reusability, you can define your tools, prompts, resources, and templates in separate files using the `defineTool`, `definePrompt`, `defineResource`, and `defineTemplate` utilities. This approach allows you to:223 224- **Organize by feature**: Group related tools in feature-specific modules225- **Reuse across servers**: Share common tools between different MCP servers226 227### Example Structure228 229```javascript230// tools/calculator.js231import { defineTool } from 'tmcp/tool';232import { z } from 'zod';233 234export const addTool = defineTool(235	{236		name: 'add',237		description: 'Add two numbers',238		schema: z.object({239			a: z.number(),240			b: z.number(),241		}),242	},243	async ({ a, b }) => ({244		content: [{ type: 'text', text: `${a} + ${b} = ${a + b}` }],245	}),246);247 248export const multiplyTool = defineTool(249	{250		name: 'multiply',251		description: 'Multiply two numbers',252		schema: z.object({253			a: z.number(),254			b: z.number(),255		}),256	},257	async ({ a, b }) => ({258		content: [{ type: 'text', text: `${a} × ${b} = ${a * b}` }],259	}),260);261```262 263```javascript264// prompts/code-review.js265import { definePrompt } from 'tmcp/prompt';266import { z } from 'zod';267 268export const codeReviewPrompt = definePrompt(269	{270		name: 'code-review',271		description: 'Generate code review prompt',272		schema: z.object({273			code: z.string(),274			language: z.string(),275		}),276	},277	async ({ code, language }) => ({278		messages: [279			{280				role: 'user',281				content: {282					type: 'text',283					text: `Review this ${language} code:\n\n${code}`,284				},285			},286		],287	}),288);289```290 291```javascript292// resources/files.js293import { defineResource } from 'tmcp/resource';294import { readFile } from 'node:fs/promises';295 296export const readmeResource = defineResource(297	{298		name: 'readme',299		description: 'Project README file',300		uri: 'file://README.md',301	},302	async (uri) => ({303		contents: [304			{305				uri,306				mimeType: 'text/markdown',307				text: await readFile(uri.replace('file://', ''), 'utf8'),308			},309		],310	}),311);312```313 314```javascript315// templates/user-files.js316import { defineTemplate } from 'tmcp/template';317import { getUserFile } from '../api/users.js';318 319export const userFileTemplate = defineTemplate(320	{321		name: 'user-files',322		description: 'Access user files by ID',323		uri: 'users/{userId}/files/{filename}',324		complete: {325			userId: async (arg) => ({326				completion: {327					values: await searchUserIds(arg),328					hasMore: false,329				},330			}),331		},332	},333	async (uri, { userId, filename }) => ({334		contents: [335			{336				uri,337				mimeType: 'text/plain',338				text: await getUserFile(userId, filename),339			},340		],341	}),342);343```344 345```javascript346// server.js347import { McpServer } from 'tmcp';348import { ZodJsonSchemaAdapter } from '@tmcp/adapter-zod';349import { addTool, multiplyTool } from './tools/calculator.js';350import { codeReviewPrompt } from './prompts/code-review.js';351import { readmeResource } from './resources/files.js';352import { userFileTemplate } from './templates/user-files.js';353 354const server = new McpServer(355	{356		name: 'my-server',357		version: '1.0.0',358	},359	{360		adapter: new ZodJsonSchemaAdapter(),361	},362);363 364// Register multiple tools at once365server.tools([addTool, multiplyTool]);366 367// Or register individually368server.tool(addTool);369 370// Same for prompts, resources, and templates371server.prompts([codeReviewPrompt]);372server.resources([readmeResource]);373server.templates([userFileTemplate]);374```375 376Adding the primitive to the server will error if the tool uses a different validation library than the one expressed in the adapter.377 378## API Reference379 380### McpServer381 382The main server class that handles MCP protocol communications.383 384#### Constructor385 386```javascript387new McpServer(serverInfo, options);388```389 390- `serverInfo`: Server metadata (name, version, description)391- `options`: Configuration object with optional adapter (for schema conversion) and capabilities392 393> [!IMPORTANT]394> While the adapter is optional (you can opt out by explicitly passing `adapter: undefined`) without an adapter the server cannot accept inputs, produce structured outputs, or request elicitations at all only do this for very simple servers.395 396#### Methods397 398##### `tool(definition, handler)` / `tools(definitions)`399 400Register one or more tools with optional schema validation.401 402```javascript403// Register a single tool inline404server.tool(405	{406		name: 'tool-name',407		description: 'Tool description',408		schema: yourSchema, // optional409	},410	async (input) => {411		// Tool implementation412		return result;413	},414);415 416// Register a tool created with defineTool417import { defineTool } from 'tmcp/tool';418 419const myTool = defineTool(420	{421		name: 'tool-name',422		description: 'Tool description',423		schema: yourSchema,424	},425	async (input) => {426		return result;427	},428);429 430server.tool(myTool);431 432// Register multiple tools at once433server.tools([tool1, tool2, tool3]);434```435 436`sessionInfo` contains the latest `clientCapabilities`, `clientInfo`, and `logLevel` reported by the connected client. Built-in transports populate it automatically, so every handler can branch on client features without additional bookkeeping.437 438##### `prompt(definition, handler)` / `prompts(definitions)`439 440Register one or more prompt templates with optional schema validation.441 442```javascript443// Register a single prompt inline444server.prompt(445  {446	name: 'prompt-name',447	description: 'Prompt description',448	schema: yourSchema, // optional449	complete: (arg, context) => ['completion1', 'completion2'] // optional450  },451  async (input) => {452	// Prompt implementation453	return { messages: [...] };454  }455);456 457// Register a prompt created with definePrompt458import { definePrompt } from 'tmcp/prompt';459 460const myPrompt = definePrompt(461  {462	name: 'prompt-name',463	description: 'Prompt description',464	schema: yourSchema,465  },466  async (input) => {467	return { messages: [...] };468  }469);470 471server.prompt(myPrompt);472 473// Register multiple prompts at once474server.prompts([prompt1, prompt2, prompt3]);475```476 477##### `resource(definition, handler)` / `resources(definitions)`478 479Register one or more static resources.480 481```javascript482// Register a single resource inline483server.resource(484  {485	name: 'resource-name',486	description: 'Resource description',487	uri: 'file://path/to/resource'488  },489  async (uri, params) => {490	// Resource implementation491	return { contents: [...] };492  }493);494 495// Register a resource created with defineResource496import { defineResource } from 'tmcp/resource';497 498const myResource = defineResource(499  {500	name: 'resource-name',501	description: 'Resource description',502	uri: 'file://path/to/resource'503  },504  async (uri) => {505	return { contents: [...] };506  }507);508 509server.resource(myResource);510 511// Register multiple resources at once512server.resources([resource1, resource2, resource3]);513```514 515##### `template(definition, handler)` / `templates(definitions)`516 517Register one or more URI templates for dynamic resources.518 519```javascript520// Register a single template inline521server.template(522  {523	name: 'template-name',524	description: 'Template description',525	uri: 'file://path/{id}/resource',526	complete: (arg, context) => ['id1', 'id2'] // optional527  },528  async (uri, params) => {529	// Template implementation using params.id530	return { contents: [...] };531  }532);533 534// Register a template created with defineTemplate535import { defineTemplate } from 'tmcp/template';536 537const myTemplate = defineTemplate(538  {539	name: 'template-name',540	description: 'Template description',541	uri: 'file://path/{id}/resource',542  },543  async (uri, params) => {544	return { contents: [...] };545  }546);547 548server.template(myTemplate);549 550// Register multiple templates at once551server.templates([template1, template2, template3]);552```553 554##### `withContext<T>()`555 556Specify the type of custom context for type-safe access to application-specific data.557 558```javascript559interface MyCustomContext {560    userId: string;561    permissions: string[];562    database: DatabaseConnection;563}564 565const server = new McpServer(serverInfo, options).withContext<MyCustomContext>();566 567// Now you can access typed custom context in handlers568server.tool(569    {570        name: 'get-user-data',571        description: 'Get current user data',572    },573    async () => {574        const { userId, database } = server.ctx.custom!;575        const userData = await database.users.findById(userId);576        return {577            content: [{ type: 'text', text: JSON.stringify(userData) }],578        };579    },580);581```582 583##### `ctx`584 585Access the current request context, including session ID, auth info, client metadata, and custom context.586 587```javascript588server.tool(589	{590		name: 'context-aware-tool',591		description: 'Tool that uses request context',592	},593	async () => {594		const { sessionId, auth, sessionInfo, custom } = server.ctx;595 596		if (!custom?.userId) {597			throw new Error('User authentication required');598		}599 600		if (sessionInfo?.clientInfo) {601			console.log(`Serving ${sessionInfo.clientInfo.name}`);602		}603 604		return {605			content: [606				{607					type: 'text',608					text: `Hello user ${custom.userId} in session ${sessionId}`,609				},610			],611		};612	},613);614```615 616##### `receive(request, context?)`617 618Process an incoming MCP request with optional context.619 620```javascript621// Basic usage622const response = server.receive(jsonRpcRequest);623 624// With custom context (typically used by transports)625const response = server.receive(jsonRpcRequest, {626	sessionId: 'session-123',627	auth: authInfo,628	sessionInfo: {629		clientCapabilities,630		clientInfo,631		logLevel,632	},633	custom: customContextData,634});635```636 637##### `request({ method, params })`638 639Send a raw JSON-RPC request to the connected client. This lets you call640experimental MCP APIs or proprietary extensions before they gain a dedicated641method on `McpServer` or to send a request with a custom JSON-schema that is not expressible with your validation library.642 643```javascript644const response = await server.request({645	method: 'elicitation/create',646	params: {647		message: 'Describe the deployment plan',648		requestedSchema: {649			type: 'object',650			required: ['region', 'replicas', 'features'],651			properties: {652				region: {653					type: 'string',654					enum: ['us-east-1', 'us-west-2', 'eu-central-1'],655				},656				replicas: { type: 'integer', minimum: 1, maximum: 20 },657				features: {658					type: 'array',659					items: {660						type: 'string',661						enum: ['canary', 'observability', 'autoscaling'],662					},663					minItems: 1,664				},665			},666		},667	},668});669```670 671- `method`: Fully qualified MCP client method name672- `params` (optional): JSON-RPC params object/array accepted by that method673 674Handle the resolved payload like any other JSON-RPC response—cast or (better) validate675as needed when using this escape hatch.676 677##### `elicitation(schema)`678 679Request client elicitation with schema validation.680 681```javascript682const result = await server.elicitation(schema);683```684 685##### `message(request)`686 687Request language model sampling from the client.688 689```javascript690const result = await server.message({691	messages: [692		{693			role: 'user',694			content: { type: 'text', text: 'Hello!' },695		},696	],697});698```699 700##### `refreshRoots()`701 702Refresh the roots list from the client.703 704```javascript705await server.refreshRoots();706console.log(server.roots); // Access current roots707```708 709##### `changed(type, id)`710 711Send notifications for subscriptions. When you call `changed('resource', uri)` the server now emits a broadcast notification, and the built-in transports look up which sessions subscribed to that URI before delivering it.712 713```javascript714server.changed('resource', 'file://path/to/resource');715```716 717##### `progress(progress, total?, message?)`718 719Report progress during long-running operations. Progress notifications are only sent when a progress token is provided by the client in the request's `_meta.progressToken` field.720 721```javascript722server.tool(723	{724		name: 'process-large-file',725		description: 'Process a large file with progress updates',726	},727	async (input) => {728		const totalSteps = 100;729 730		for (let i = 0; i <= totalSteps; i++) {731			// Report progress with current step, total steps, and optional message732			server.progress(733				i,734				totalSteps,735				`Processing step ${i}/${totalSteps}`,736			);737 738			// Simulate work739			await processStep(i);740		}741 742		return {743			content: [{ type: 'text', text: 'Processing complete!' }],744		};745	},746);747```748 749**Parameters:**750 751- `progress` (number): Current progress value (should be ≤ total and always increase)752- `total` (number, optional): Maximum progress value (defaults to 1)753- `message` (string, optional): Descriptive message about current progress754 755**Notes:**756 757- Progress notifications are only sent when the client provides a `progressToken` in the request758- Progress values should be monotonically increasing within a single operation759- Each session maintains its own progress context760 761##### `log(level, data, logger?)`762 763Send log messages to connected clients when logging is enabled.764 765```javascript766// Log at different severity levels767server.log('info', 'Server started successfully');768server.log('warning', 'Configuration missing, using defaults');769server.log('error', 'Failed to connect to database', 'database-logger');770```771 772**Parameters:**773 774- `level` (string): Log level ('debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency')775- `data` (any): Data to log776- `logger` (string, optional): Logger name/category777 778##### `on(event, callback)`779 780Listen to server events.781 782Available events:783 784- `initialize` – fired after the client handshake with the parsed initialize payload785- `send` – emitted for point-to-point responses/notifications destined for the active session786- `broadcast` – emitted for fan-out notifications (for example `notifications/resources/updated`)787- `subscription` – raised when the client subscribes to a resource URI788- `loglevelchange` – fired when the client requests a different log level789 790```javascript791server.on('initialize', ({ clientInfo }) => {792	console.log('Client initialized:', clientInfo?.name);793});794 795server.on('send', ({ request }) => {796	console.log('Sending message:', request);797});798 799server.on('broadcast', ({ request }) => {800	console.log('Broadcasting:', request.method);801});802```803 804## Advanced Examples805 806### Progress Reporting807 808Provide real-time progress updates for long-running operations:809 810```javascript811server.tool(812	{813		name: 'analyze-codebase',814		description: 'Analyze a large codebase with progress tracking',815		schema: z.object({816			path: z.string(),817			includeTests: z.boolean().default(false),818		}),819	},820	async ({ path, includeTests }) => {821		// Discover files to analyze822		const files = await discoverFiles(path, includeTests);823		const totalFiles = files.length;824 825		server.progress(0, totalFiles, 'Starting analysis...');826 827		const results = [];828		for (let i = 0; i < files.length; i++) {829			const file = files[i];830 831			// Update progress with current file being processed832			server.progress(833				i + 1,834				totalFiles,835				`Analyzing ${file} (${i + 1}/${totalFiles})`,836			);837 838			// Analyze the file839			const analysis = await analyzeFile(file);840			results.push(analysis);841		}842 843		// Final progress update844		server.progress(totalFiles, totalFiles, 'Analysis complete!');845 846		return {847			content: [848				{849					type: 'text',850					text: `Analyzed ${totalFiles} files. Found ${results.length} issues.`,851				},852			],853			structuredContent: {854				totalFiles,855				results,856				issues: results.length,857			},858		};859	},860);861 862// Progress also works in prompts and resources863server.prompt(864	{865		name: 'generate-report',866		description: 'Generate a comprehensive report',867		schema: z.object({868			sections: z.array(z.string()),869		}),870	},871	async ({ sections }) => {872		const messages = [];873 874		for (let i = 0; i < sections.length; i++) {875			server.progress(876				i,877				sections.length,878				`Generating section: ${sections[i]}`,879			);880 881			const content = await generateSection(sections[i]);882			messages.push({883				role: 'user',884				content: { type: 'text', text: content },885			});886		}887 888		server.progress(sections.length, sections.length, 'Report complete');889		return { messages };890	},891);892```893 894### Client Interaction Features895 896```javascript897// Elicitation - Request structured data from client898const userData = await server.elicitation(899	z.object({900		name: z.string(),901		age: z.number(),902		preferences: z.array(z.string()),903	}),904);905 906// Message sampling - Request AI responses907const aiResponse = await server.message({908	messages: [909		{910			role: 'user',911			content: { type: 'text', text: 'Explain quantum computing' },912		},913	],914	maxTokens: 100,915});916 917// Roots management - Access client's filesystem roots918await server.refreshRoots();919console.log('Available roots:', server.roots);920```921 922### Event Handling923 924```javascript925// Listen to server events926server.on('initialize', (data) => {927	console.log('Client capabilities:', data.capabilities);928});929 930server.on('send', ({ request }) => {931	console.log('Outgoing request:', request.method);932});933 934server.on('broadcast', ({ request }) => {935	if (request.method === 'notifications/resources/updated') {936		console.log('Resource updated:', request.params.uri);937	}938});939```940 941### Resource Subscriptions942 943```javascript944// Subscribe to resource changes945server.resource(946	{947		name: 'file-watcher',948		description: 'Watch file changes',949		uri: 'file://watched/file.txt',950	},951	async (uri) => {952		return {953			contents: [954				{955					uri,956					mimeType: 'text/plain',957					text: await readFile(uri),958				},959			],960		};961	},962);963 964// Notify subscribers when resource changes965server.changed('resource', 'file://watched/file.txt');966```967 968### Completion API969 970The completion API allows you to provide auto-completion suggestions for prompt and template parameters. Completion functions return an object with `completion` containing `values`, `total`, and `hasMore` properties.971 972#### Completion Response Format973 974```javascript975{976  completion: {977    values: string[],      // Array of completion values (max 100 items)978    total?: number,        // Total number of available completions979    hasMore?: boolean      // Whether there are more completions available980  }981}982```983 984#### Prompt Parameter Completion985 986```javascript987server.prompt(988	{989		name: 'story-generator',990		description: 'Generate a story with specific parameters',991		schema: z.object({992			genre: z.string(),993			length: z.enum(['short', 'medium', 'long']),994			character: z.string(),995		}),996		complete: {997			genre: (arg, context) => {998				const genres = [999					'fantasy',1000					'sci-fi',1001					'mystery',1002					'romance',1003					'thriller',1004				];1005				const filtered = genres.filter((g) =>1006					g.startsWith(arg.toLowerCase()),1007				);1008 1009				return {1010					completion: {1011						values: filtered,1012						total: filtered.length,1013						hasMore: false,1014					},1015				};1016			},1017			length: (arg, context) => {1018				const lengths = ['short', 'medium', 'long'];1019				const filtered = lengths.filter((l) => l.includes(arg));1020 1021				return {1022					completion: {1023						values: filtered,1024						total: filtered.length,1025						hasMore: false,1026					},1027				};1028			},1029			character: (arg, context) => {1030				// Dynamic completion based on genre1031				const characters = {1032					fantasy: ['wizard', 'dragon', 'knight', 'elf'],1033					'sci-fi': ['robot', 'alien', 'cyborg', 'space-explorer'],1034					mystery: ['detective', 'suspect', 'witness', 'victim'],1035					default: ['hero', 'villain', 'sidekick', 'mentor'],1036				};1037 1038				const genre = context.params?.genre || 'default';1039				const charList = characters[genre] || characters.default;1040				const filtered = charList.filter((c) => c.includes(arg));1041 1042				return {1043					completion: {1044						values: filtered,1045						total: filtered.length,1046						hasMore: false,1047					},1048				};1049			},1050		},1051	},1052	async (input) => {1053		return {1054			description: `A ${input.length} ${input.genre} story featuring a ${input.character}`,1055			messages: [1056				{1057					role: 'user',1058					content: {1059						type: 'text',1060						text: `Write a ${input.length} ${input.genre} story featuring a ${input.character}.`,1061					},1062				},1063			],1064		};1065	},1066);1067```1068 1069#### Resource Template Completion1070 1071```javascript1072server.template(1073	{1074		name: 'user-profile',1075		description: 'Get user profile by ID',1076		uri: 'users/{userId}/profile',1077		complete: {1078			userId: (arg, context) => {1079				// Filter users based on the current input1080				const allUsers = ['user1', 'user2', 'user3', 'admin-user'];1081				const filtered = allUsers.filter((id) => id.includes(arg));1082 1083				return {1084					completion: {1085						values: filtered.slice(0, 10), // Limit to 10 results1086						total: filtered.length,1087						hasMore: filtered.length > 10,1088					},1089				};1090			},1091		},1092	},1093	async (uri, params) => {1094		const user = await getUserById(params.userId);1095		return {1096			contents: [1097				{1098					uri,1099					mimeType: 'application/json',1100					text: JSON.stringify(user),1101				},1102			],1103		};1104	},1105);1106```1107 1108#### Advanced Completion Examples1109 1110```javascript1111// Completion with async data fetching1112server.template(1113	{1114		name: 'project-files',1115		description: 'Access project files by path',1116		uri: 'projects/{projectId}/files/{filePath}',1117		complete: {1118			projectId: (arg, context) => {1119				// Static list of project IDs1120				const projects = ['web-app', 'mobile-app', 'api-server'];1121				const filtered = projects.filter((p) => p.includes(arg));1122 1123				return {1124					completion: {1125						values: filtered,1126						total: filtered.length,1127						hasMore: false,1128					},1129				};1130			},1131			filePath: async (arg, context) => {1132				// Dynamic file path completion based on project1133				const projectId = context.params?.projectId;1134				if (!projectId) {1135					return {1136						completion: {1137							values: [],1138							total: 0,1139							hasMore: false,1140						},1141					};1142				}1143 1144				// Simulate fetching files from filesystem1145				const files = await getProjectFiles(projectId);1146				const filtered = files.filter((f) => f.includes(arg));1147 1148				return {1149					completion: {1150						values: filtered.slice(0, 20),1151						total: filtered.length,1152						hasMore: filtered.length > 20,1153					},1154				};1155			},1156		},1157	},1158	async (uri, params) => {1159		const content = await readProjectFile(1160			params.projectId,1161			params.filePath,1162		);1163		return {1164			contents: [1165				{1166					uri,1167					mimeType: 'text/plain',1168					text: content,1169				},1170			],1171		};1172	},1173);1174 1175// Completion with pagination support1176server.prompt(1177	{1178		name: 'search-documents',1179		description: 'Search through large document collection',1180		schema: z.object({1181			query: z.string(),1182			category: z.string(),1183		}),1184		complete: {1185			category: (arg, context) => {1186				// Large category list with pagination1187				const allCategories = generateCategoryList(); // Assume this returns 500+ items1188				const filtered = allCategories.filter((c) =>1189					c.toLowerCase().includes(arg.toLowerCase()),1190				);1191 1192				return {1193					completion: {1194						values: filtered.slice(0, 50), // Show first 50 matches1195						total: filtered.length,1196						hasMore: filtered.length > 50,1197					},1198				};1199			},1200		},

Showing the first 1,200 of 1524 lines. Download the file for the rest.

Brunobkr/llama.cpp_AlgMor24_github · Team Ai