Files
gronod 7bcf5322e1 feat: emby-mcp 1.0.16 player owner filter and HA links
Expose session/last-used user and device IP on player rows. Filter
retrieve_player_list by users, merge GET /Devices when include_offline
is set, and resolve spoken names to HA media_player entities via
player_links (device_id or IP). PlayNow still requires a live session.
2026-09-25 19:58:58 +00:00

60 lines
1.8 KiB
Go

// Package server wires the Emby tools into an MCP server using the official
// modelcontextprotocol go-sdk.
package server
import (
"encoding/json"
"fmt"
"log"
"git.i3omb.com/gronod/emby-mcp/internal/state"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
const (
Name = "HA Emby MCP"
Version = "1.0.16"
Purpose = `These MCP tools allow you to control an Emby media server. Using them you can retrieve
a list of libraries, genres, playlists, audio & video items, and player sessions.
You can browse series, seasons and episodes, find the next episode to watch,
inspect a player's now-playing audio/subtitle tracks, add items to playlists,
and play, pause, seek and stop items on a player session.`
)
// New builds the MCP server and registers all tools against the shared state.
func New(st *state.State) *mcp.Server {
s := mcp.NewServer(
&mcp.Implementation{Name: Name, Version: Version},
&mcp.ServerOptions{Instructions: Purpose},
)
registerUserTools(s, st)
registerLibraryTools(s, st)
registerItemTools(s, st)
registerBrowseTools(s, st)
registerPlaylistTools(s, st)
registerPlayerTools(s, st)
return s
}
// errf logs to stderr and returns the message in the Python "ERROR: ..." style.
func errf(format string, args ...any) string {
msg := fmt.Sprintf(format, args...)
log.Printf("%s", msg)
return msg
}
// textResult wraps a string as MCP text content (the Python tools all return
// bare strings — JSON documents or error messages).
func textResult(s string) *mcp.CallToolResult {
return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: s}}}
}
// jsonResult marshals v to JSON text; on failure returns an error string.
func jsonResult(v any) *mcp.CallToolResult {
b, err := json.Marshal(v)
if err != nil {
return textResult(errf("ERROR: failed to encode result as JSON: %v", err))
}
return textResult(string(b))
}