From 562a7776ca42caf3b1bb93238f2e7624fe40c629 Mon Sep 17 00:00:00 2001 From: Amolith Date: Tue, 28 Apr 2026 17:14:06 -0600 Subject: [PATCH] tools: replace instructions with usage tool --- internal/server/server.go | 32 +++++++++++++++++++++++++++----- internal/server/tools.go | 3 +++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/internal/server/server.go b/internal/server/server.go index bf4391437d23b8d7ae2b26db7b19a80f71df6e1f..8e8723b61ccd08490176f298787a2235631f1549 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -37,14 +37,13 @@ func New(cfg *config.Config) *mcp.Server { server := mcp.NewServer(&mcp.Implementation{ Name: "sb-mcp", Version: Version, - }, &mcp.ServerOptions{ - Instructions: Instructions, - }) + }, &mcp.ServerOptions{}) // Register tools with the SB client closed over mcp.AddTool(server, &mcp.Tool{ - Name: "execute_lua", - Description: "Execute a Space Lua script on the SilverBullet instance. Use 'return' to send results back. 'print()' output is not captured.", + Name: "execute_lua", + Description: "Execute a Space Lua script on the SilverBullet instance. " + + "Always call `usage` first to load the Space Lua reference and API guide.", Annotations: &mcp.ToolAnnotations{ Title: "Execute Lua", ReadOnlyHint: false, @@ -76,6 +75,18 @@ func New(cfg *config.Config) *mcp.Server { }, }, makeConsoleLogsHandler(sbClient)) + mcp.AddTool(server, &mcp.Tool{ + Name: "usage", + Description: "Load the full SilverBullet usage guide: Space Lua syntax, available APIs (space.*, editor.*, net.*, query), gotchas, and best practices. " + + "Always call this before `execute_lua`.", + Annotations: &mcp.ToolAnnotations{ + Title: "Usage Guide", + ReadOnlyHint: true, + IdempotentHint: true, + OpenWorldHint: ptrBool(false), + }, + }, makeUsageHandler()) + return server } @@ -185,6 +196,17 @@ func makeConsoleLogsHandler(client *silverbullet.Client) func(context.Context, * } } +// makeUsageHandler returns a tool handler that returns the embedded SilverBullet usage guide. +func makeUsageHandler() func(context.Context, *mcp.CallToolRequest, UsageParams) (*mcp.CallToolResult, any, error) { + return func(_ context.Context, _ *mcp.CallToolRequest, _ UsageParams) (*mcp.CallToolResult, any, error) { + return &mcp.CallToolResult{ + Content: []mcp.Content{ + &mcp.TextContent{Text: Instructions}, + }, + }, nil, nil + } +} + // formatLuaResult formats a JSON result from Lua execution for display. // JSON strings are unescaped to plain text (so markdown content reads cleanly). // All other values (numbers, bools, null, objects, arrays) pass through as raw JSON. diff --git a/internal/server/tools.go b/internal/server/tools.go index d938176ab22995ad9e6ab1a2655be461f88f9a91..f4906472f496890209d4baf9ee3ec4c5fdb850d4 100644 --- a/internal/server/tools.go +++ b/internal/server/tools.go @@ -19,3 +19,6 @@ type ConsoleLogsParams struct { Limit int `json:"limit,omitempty" jsonschema:"Maximum number of log entries to return (1-1000,default=100)"` Since int64 `json:"since,omitempty" jsonschema:"Only return entries newer than this unix millisecond timestamp (optional)"` } + +// UsageParams is empty because there are none :D . +type UsageParams struct{}