Add HighLevelOverviewTool

This commit is contained in:
Dominik Jain 2025-09-20 17:40:43 +02:00 committed by Dominik Jain
parent b94f29fcf1
commit bc28e116c8
6 changed files with 44 additions and 20 deletions

View File

@ -1 +1,3 @@
*.md
*.yml

View File

@ -22,3 +22,5 @@ initial_instructions: |
generateMarkup(shapes: Shape[], options?: {
type?: "html" | "svg";
}): string;
You have hereby read the 'Penpot High-Level Overview' and need not use a tool to read it again.

View File

@ -9,7 +9,7 @@ import { createLogger } from "./logger.js";
*/
export interface PromptsConfig {
/** Initial instructions displayed when the server starts or connects to a client */
initial_instructions?: string;
initial_instructions: string;
[key: string]: any; // Allow for future extension with additional prompt types
}
@ -51,24 +51,16 @@ export class ConfigurationLoader {
const promptsPath = join(this.baseDir, "..", "data", "prompts.yml");
if (!existsSync(promptsPath)) {
this.logger.warn(`Prompts configuration file not found at ${promptsPath}, using defaults`);
this.promptsConfig = {};
return this.promptsConfig;
throw new Error(`Prompts configuration file not found at ${promptsPath}, using defaults`);
}
try {
const fileContent = readFileSync(promptsPath, "utf8");
const parsedConfig = yaml.load(fileContent) as PromptsConfig;
const fileContent = readFileSync(promptsPath, "utf8");
const parsedConfig = yaml.load(fileContent) as PromptsConfig;
this.promptsConfig = parsedConfig || {};
this.logger.info(`Loaded prompts configuration from ${promptsPath}`);
this.promptsConfig = parsedConfig || {};
this.logger.info(`Loaded prompts configuration from ${promptsPath}`);
return this.promptsConfig;
} catch (error) {
this.logger.error(error, `Failed to load prompts configuration from ${promptsPath}`);
this.promptsConfig = {};
return this.promptsConfig;
}
return this.promptsConfig;
}
/**
@ -76,7 +68,7 @@ export class ConfigurationLoader {
*
* @returns The initial instructions string, or undefined if not configured
*/
public getInitialInstructions(): string | undefined {
public getInitialInstructions(): string {
const config = this.getPromptsConfig();
return config.initial_instructions;
}

View File

@ -9,6 +9,7 @@ import { PluginBridge } from "./PluginBridge";
import { ConfigurationLoader } from "./ConfigurationLoader";
import { createLogger } from "./logger";
import { Tool } from "./Tool";
import { HighLevelOverviewTool } from "./tools/HighLevelOverviewTool";
export class PenpotMcpServer {
private readonly logger = createLogger("PenpotMcpServer");
@ -29,7 +30,6 @@ export class PenpotMcpServer {
this.port = port;
const instructions = this.configLoader.getInitialInstructions();
this.logger.info("Instructions: %s", instructions ?? "<none>");
this.server = new McpServer(
{
name: "penpot-mcp-server",
@ -46,11 +46,16 @@ export class PenpotMcpServer {
this.registerTools();
}
public getInitialInstructions(): string {
return this.configLoader.getInitialInstructions();
}
private registerTools(): void {
const toolInstances: Tool<any>[] = [
new HelloWorldTool(this),
new PrintTextTool(this),
new ExecuteCodeTool(this),
new HighLevelOverviewTool(this),
];
for (const tool of toolInstances) {

View File

@ -1,7 +1,4 @@
import { z } from "zod";
import { Tool as MCPTool } from "@modelcontextprotocol/sdk/types.js";
import { validate, ValidationError } from "class-validator";
import { plainToClass } from "class-transformer";
import "reflect-metadata";
import { TextResponse, ToolResponse } from "./ToolResponse";
import type { PenpotMcpServer } from "./PenpotMcpServer";

View File

@ -0,0 +1,26 @@
import { EmptyToolArgs, Tool } from "../Tool";
import "reflect-metadata";
import type { ToolResponse } from "../ToolResponse";
import { TextResponse } from "../ToolResponse";
import { PenpotMcpServer } from "../PenpotMcpServer";
export class HighLevelOverviewTool extends Tool<EmptyToolArgs> {
constructor(mcpServer: PenpotMcpServer) {
super(mcpServer, EmptyToolArgs.schema);
}
public getToolName(): string {
return "high_level_overview";
}
public getToolDescription(): string {
return (
"Returns basic high-level instructions on the usage of Penpot-related tools and the Penpot API. " +
"If you have already read the 'Penpot High-Level Overview', you must not call this tool."
);
}
protected async executeCore(args: EmptyToolArgs): Promise<ToolResponse> {
return new TextResponse(this.mcpServer.getInitialInstructions());
}
}