UNPKG

@progress/telerik-blazor-mcp

Version:

Model Context Protocol for Blazor

34 lines (27 loc) 7.78 kB
#!/usr/bin/env node var w=Object.defineProperty;var P=(e,t,o)=>t in e?w(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o;var h=(e,t,o)=>P(e,typeof t!="symbol"?t+"":t,o);import{McpServer as O}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as F}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as y}from"zod";var m="Telerik UI for Blazor",S="blazor",I=["AIPrompt","AnimationContainer","AppBar","ArcGauge","AutoComplete","Avatar","Badge","Barcode","Breadcrumb","Button","ButtonGroup","Calendar","Card","Carousel","Charts","Chat","Checkbox","Chip","ChipList","ChunkProgressBar","CircularGauge","ColorGradient","ColorPalette","ColorPicker","ComboBox","ContextMenu","DateInput","DatePicker","DateRangePicker","DateTimePicker","Diagram","Dialog","DockManager","Drawer","DropDownButton","DropDownList","DropZone","Editor","FileManager","FileSelect","Filter","FlatColorPicker","FloatingActionButton","FloatingLabel","FontIcon","Form","Gantt","Grid","GridLayout","InlineAIPrompt","InstallerandVSExtensions","LinearGauge","ListBox","ListView","Loader","LoaderContainer","Map","MaskedTextBox","MediaQuery","Menu","MultiColumnComboBox","MultiSelect","Notification","NumericTextBox","PageTemplatesAndBuildingBlocks","Pager","PanelBar","PDFViewer","PivotGrid","Popover","Popup","ProgressBar","QRCode","RadialGauge","RadioGroup","RangeSlider","Rating","Sankey","Scheduler","Signature","Skeleton","Slider","SpeechToTextButton","SplitButton","Splitter","Spreadsheet","StackLayout","Stepper","StockChart","SvgIcon","Switch","TabStrip","TextArea","TextBox","TileLayout","TimePicker","ToggleButton","ToolBar","Tooltip","TreeList","TreeView","Upload","ValidationMessage","ValidationSummary","ValidationTooltip","VSCodeExtension","Window","Wizard","General"];import{dirname as b,join as N}from"path";import{fileURLToPath as B}from"url";import{loadLicense as v,decodeLicenseKey as _,decodeLicenseEvidence as D}from"@progress/kendo-licensing/utils";import a from"node:fs";import g from"node:path";import U from"@grpc/proto-loader";import d from"@grpc/grpc-js";var E=class extends Error{constructor(e){super(e),this.name="LicenseError"}};async function L(){let e=v();if(!e.success)throw new E(e.message);return(await _(e.value)).licenses.find(async o=>!!(await D(o)).userId)||e.value}var f=!1,i=process.env.DEBUG_LOG_FILE,T=!!(i&&typeof i=="string");if(T){let e=g.resolve(i),t=g.dirname(e);if(t!=="."&&t!==process.cwd()&&!a.existsSync(t))try{a.mkdirSync(t,{recursive:!0})}catch(o){console.error("Error creating log directory:",o)}if(!a.existsSync(e))try{a.writeFileSync(e,"")}catch(o){console.error("Error creating log file:",o)}}else f=!1;f=T&&!!i&&a.existsSync(g.resolve(i));function n(...e){if(f&&i){let t=`${new Date().toISOString()}: ${e.join(" ")} `,o=g.resolve(i);a.appendFile(o,t,r=>{r&&console.error("Error writing to log file:",r)})}}var c=(e=>(e[e.UNAUTHENTICATED=16]="UNAUTHENTICATED",e[e.RESOURCE_EXHAUSTED=8]="RESOURCE_EXHAUSTED",e[e.PERMISSION_DENIED=7]="PERMISSION_DENIED",e))(c||{}),C=class{constructor(e,t){h(this,"client");h(this,"isDev");this.contextApiUrl=e,this.protoPath=t;let o=U.loadSync(this.protoPath,{keepCase:!0,longs:String,enums:String,defaults:!0,oneofs:!0});this.isDev=this.contextApiUrl?.includes("localhost")||this.contextApiUrl?.includes("127.0.0.1"),n("Using ContextApi URl:",this.contextApiUrl);let r=d.loadPackageDefinition(o);this.client=new r.ContextQueryService(this.contextApiUrl||"contextapi.telerik.com:443",this.isDev?d.credentials.createInsecure():d.credentials.createSsl())}async query(e){let t=this.isDev?"fake_license":await L(),o=process.env.CONTEXTAPI_API_KEY,r=new d.Metadata;if(t&&typeof t=="string"){t=t.replace(/^\uFEFF/,"");try{r.add("x-license-key",t)}catch(s){return n("Error adding license key to metadata:",s),Promise.reject(new Error(`Failed to use license key: ${s.message}`))}}return o&&typeof o=="string"&&r.add("x-api-key",o),new Promise((s,l)=>{this.client.query(e,r,(u,p)=>{u?l(u):s(p)})})}};var R=N(b(B(import.meta.url)),"../proto/service.proto"),M=new C("contextapi.telerik.com:443",R);async function k(e){return M.query(e)}import z from"fs";import x from"path";import{fileURLToPath as q}from"url";var G=q(import.meta.url),V=x.dirname(G),H=x.resolve(V,"../package.json"),$=JSON.parse(z.readFileSync(H,"utf-8")),A=new O({name:"telerik-and-kendo-resources",version:$.version});A.tool("telerik_blazor_assistant",`Answers questions and retrieves documentation about Telerik UI for Blazor. Use this tool when the user asks about Telerik UI for Blazor features, specific components (e.g., Grid, Chart, Editor), implementation details, or general usage. Provide the exact user's question as the 'query'. If the question pertains to a specific Telerik UI for Blazor component, specify its name in the 'component' parameter. If the user's question pertains to or mentions icon usage in any way, such as asking about components that may contain icons (e.g., buttons) or directly about icons, set the 'queryInvolvesIcons' parameter to true. This tool can be automatically triggered when the following phrases are detected in the user's input/prompt: - 'Telerik'; - '/telerik'; - '/telerikblazor' - '/ask_telerik'; - '/help_telerik'; - '@telerik'; - '@telerikblazor'; - '@ask_telerik'; - '@help_telerik'.`,{query:y.string().describe("The query to search for."),component:y.enum(I).describe("The component to search for. If not specified, you can use General."),queryInvolvesIcons:y.boolean().optional().default(!1).describe(`Set to true if the query pertains to or mentions icon usage in any way, such as asking about components that may contain icons (e.g., buttons) or directly about icons. This influences the allowed types in the API call to include icon-related content.`)},async({query:e,component:t,queryInvolvesIcons:o})=>{n("Calling tool: ",JSON.stringify({query:e,component:t,queryInvolvesIcons:o}));try{let r=await k({query:e,component:t.toLocaleLowerCase(),lib_name:S,text_matches_count:3,code_matches_count:0,allowed_types:o?["documentation","icons"]:["documentation"]});n("Response from context API: ",JSON.stringify(r));let s=J(t.toLocaleLowerCase(),o),l=r.values.join(` `),u=l.trim(),p=[{type:"text",text:l+(u?` `+s:"")}];return n("Response from tool: ",JSON.stringify(p)),{content:p}}catch(r){throw n("Error calling context API: ",JSON.stringify(r)),r?.code===c.UNAUTHENTICATED?new Error(`Error: You are not authenticated. Message: ${r.message}.`):r?.code===c.RESOURCE_EXHAUSTED?new Error(`Error: You have exceeded the extension quota. Upgrade to subscription licensing in order to unlock full access. Message: ${r.message}.`):r?.code===c.PERMISSION_DENIED?new Error(`Error: You do not have permission to access this resource. Please verify that you have a valid ${m} license key.`):r instanceof E?(n("License error: ",r.message),r):new Error(`Error: An error occurred while calling the service. Please try again later. Error Message: ${r.message}`)}});function J(e,t){let o=t?"Icon names returned from the above category are in kebab-case (e.g., 'volume-mute'), but when using them in Blazor, you must convert them to PascalCase (e.g., 'VolumeMute'). Always use PascalCase for icon names in Blazor components when using existing icons from the Progress Design System Kit.":"";return` # ${m} Assistant Guidelines ${o?`## Icon Usage ${o}`:""} ### No Attribute Splatting ${m} components do **not support attribute splatting**. Do not use \`style\`, \`class\`, or other arbitrary HTML attributes directly on Telerik components. Instead, use the component's built-in parameters (e.g., \`Class\`, \`Width\`, \`Height\`) or wrap the component in a container element to apply custom styling. `}async function K(){let e=new F;n("Starting server..."),await A.connect(e)}K();