返回 DeepSeek-Reasonix
resources.go
根目录 / internal / plugin / resources.go
1 package plugin
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "strings"
8 )
9
10 // Resource is an MCP resource a server exposes. In chat it is referenced as
11 // "@<server>:<uri>" (e.g. "@docs:file://README.md"); the referenced content is
12 // fetched and prepended to the message sent to the model.
13 type Resource struct {
14 Server string // owning server name
15 URI string // canonical resource uri
16 Name string // human-readable label
17 Description string
18 MimeType string
19 }
20
21 func (c *Client) listResources(ctx context.Context) ([]Resource, error) {
22 res, err := c.call(ctx, "resources/list", map[string]any{})
23 if err != nil {
24 return nil, err
25 }
26 var out struct {
27 Resources []struct {
28 URI string `json:"uri"`
29 Name string `json:"name"`
30 Description string `json:"description"`
31 MimeType string `json:"mimeType"`
32 } `json:"resources"`
33 }
34 if err := json.Unmarshal(res, &out); err != nil {
35 return nil, fmt.Errorf("plugin %q: decode resources/list: %w", c.name, err)
36 }
37 resources := make([]Resource, 0, len(out.Resources))
38 for _, r := range out.Resources {
39 resources = append(resources, Resource{
40 Server: c.name,
41 URI: r.URI,
42 Name: r.Name,
43 Description: r.Description,
44 MimeType: r.MimeType,
45 })
46 }
47 return resources, nil
48 }
49
50 // readResource fetches a resource by uri and flattens its text contents. Binary
51 // (blob) contents are noted but not decoded — a coding agent consumes text.
52 func (c *Client) readResource(ctx context.Context, uri string) (string, error) {
53 res, err := c.call(ctx, "resources/read", map[string]any{"uri": uri})
54 if err != nil {
55 return "", err
56 }
57 var out struct {
58 Contents []struct {
59 URI string `json:"uri"`
60 MimeType string `json:"mimeType"`
61 Text string `json:"text"`
62 Blob string `json:"blob"`
63 } `json:"contents"`
64 }
65 if err := json.Unmarshal(res, &out); err != nil {
66 return "", fmt.Errorf("plugin %q: decode resources/read: %w", c.name, err)
67 }
68 var sb strings.Builder
69 for _, ct := range out.Contents {
70 if sb.Len() > 0 {
71 sb.WriteString("\n\n")
72 }
73 switch {
74 case ct.Text != "":
75 sb.WriteString(ct.Text)
76 case ct.Blob != "":
77 fmt.Fprintf(&sb, "[binary resource %s, %s — %d base64 bytes omitted]", ct.URI, ct.MimeType, len(ct.Blob))
78 }
79 }
80 return sb.String(), nil
81 }
82
82 lines GO