219 lines
5.5 KiB
Go
219 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
)
|
|
|
|
// MCP Tool Implementations
|
|
// These call the internal API endpoints to get data
|
|
|
|
const apiBaseURL = "http://localhost:8082" // Internal API server
|
|
|
|
func mcpAPICall(accessToken, path string, params map[string]string) ([]byte, error) {
|
|
u := apiBaseURL + path
|
|
if params != nil && len(params) > 0 {
|
|
v := url.Values{}
|
|
for k, val := range params {
|
|
if val != "" {
|
|
v.Set(k, val)
|
|
}
|
|
}
|
|
u += "?" + v.Encode()
|
|
}
|
|
|
|
req, err := http.NewRequest("GET", u, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Use the access token for auth
|
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
return body, nil
|
|
}
|
|
|
|
func mcpListDossiers(accessToken string) (string, error) {
|
|
body, err := mcpAPICall(accessToken, "/api/v1/dossiers", nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Pretty print JSON
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpListStudies(accessToken, dossier string) (string, error) {
|
|
body, err := mcpAPICall(accessToken, "/api/v1/dossiers/"+dossier+"/entries", map[string]string{"category": "imaging"})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpListSeries(accessToken, dossier, study string) (string, error) {
|
|
body, err := mcpAPICall(accessToken, "/api/v1/dossiers/"+dossier+"/entries", map[string]string{"parent": study})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpListSlices(accessToken, dossier, series string) (string, error) {
|
|
body, err := mcpAPICall(accessToken, "/api/v1/dossiers/"+dossier+"/entries", map[string]string{"parent": series})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpFetchImage(accessToken, dossier, slice string, wc, ww float64) (map[string]interface{}, error) {
|
|
params := map[string]string{}
|
|
if wc != 0 {
|
|
params["wc"] = strconv.FormatFloat(wc, 'f', 0, 64)
|
|
}
|
|
if ww != 0 {
|
|
params["ww"] = strconv.FormatFloat(ww, 'f', 0, 64)
|
|
}
|
|
|
|
body, err := mcpAPICall(accessToken, "/image/"+slice, params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
b64 := base64.StdEncoding.EncodeToString(body)
|
|
return mcpImageContent(b64, "image/webp", fmt.Sprintf("Slice %s (%d bytes)", slice[:8], len(body))), nil
|
|
}
|
|
|
|
func mcpFetchContactSheet(accessToken, dossier, series string, wc, ww float64) (map[string]interface{}, error) {
|
|
params := map[string]string{}
|
|
if wc != 0 {
|
|
params["wc"] = strconv.FormatFloat(wc, 'f', 0, 64)
|
|
}
|
|
if ww != 0 {
|
|
params["ww"] = strconv.FormatFloat(ww, 'f', 0, 64)
|
|
}
|
|
|
|
body, err := mcpAPICall(accessToken, "/contact-sheet.webp/"+series, params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
b64 := base64.StdEncoding.EncodeToString(body)
|
|
return mcpImageContent(b64, "image/webp", fmt.Sprintf("Contact sheet %s (%d bytes)", series[:8], len(body))), nil
|
|
}
|
|
|
|
func mcpListLabTests(accessToken, dossier string) (string, error) {
|
|
body, err := mcpAPICall(accessToken, "/api/labs/tests", map[string]string{"dossier": dossier})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpGetLabResults(accessToken, dossier, names, from, to string, latest bool) (string, error) {
|
|
params := map[string]string{"dossier": dossier, "names": names}
|
|
if from != "" {
|
|
params["from"] = from
|
|
}
|
|
if to != "" {
|
|
params["to"] = to
|
|
}
|
|
if latest {
|
|
params["latest"] = "true"
|
|
}
|
|
|
|
body, err := mcpAPICall(accessToken, "/api/labs/results", params)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpGetCategories(accessToken, dossier, typ, category string) (string, error) {
|
|
params := map[string]string{"dossier": dossier}
|
|
if typ != "" {
|
|
params["type"] = typ
|
|
}
|
|
if category != "" {
|
|
params["category"] = category
|
|
}
|
|
|
|
body, err := mcpAPICall(accessToken, "/api/categories", params)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|
|
|
|
func mcpQueryGenome(accessToken, dossier, gene, search, category, rsids string, minMag float64, includeHidden bool) (string, error) {
|
|
params := map[string]string{"dossier": dossier}
|
|
if gene != "" {
|
|
params["gene"] = gene
|
|
}
|
|
if search != "" {
|
|
params["search"] = search
|
|
}
|
|
if category != "" {
|
|
params["category"] = category
|
|
}
|
|
if rsids != "" {
|
|
params["rsids"] = rsids
|
|
}
|
|
if minMag > 0 {
|
|
params["min_magnitude"] = strconv.FormatFloat(minMag, 'f', -1, 64)
|
|
}
|
|
if includeHidden {
|
|
params["include_hidden"] = "true"
|
|
}
|
|
|
|
body, err := mcpAPICall(accessToken, "/api/genome", params)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var data interface{}
|
|
json.Unmarshal(body, &data)
|
|
pretty, _ := json.MarshalIndent(data, "", " ")
|
|
return string(pretty), nil
|
|
}
|