Skip to content

Commit 3c629d1

Browse files
committed
add logging tools
1 parent b05d71c commit 3c629d1

File tree

14 files changed

+422
-7
lines changed

14 files changed

+422
-7
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/99designs/keyring v1.2.2
77
github.com/apache/pulsar-client-go v0.13.1
88
github.com/dgrijalva/jwt-go v3.2.0+incompatible
9-
github.com/mark3labs/mcp-go v0.23.1
9+
github.com/mark3labs/mcp-go v0.25.0
1010
github.com/mitchellh/go-homedir v1.1.0
1111
github.com/pkg/errors v0.9.1
1212
github.com/sirupsen/logrus v1.9.3
@@ -37,6 +37,7 @@ require (
3737
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
3838
github.com/fatih/color v1.7.0 // indirect
3939
github.com/ghodss/yaml v1.0.0 // indirect
40+
github.com/gmlewis/go-httpdebug v0.0.9 // indirect
4041
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
4142
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
4243
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
6969
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
7070
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
7171
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
72+
github.com/gmlewis/go-httpdebug v0.0.9 h1:zNweu7aEyDOL2bDt5tpwAMMNifai9YtAh479bZEML6g=
73+
github.com/gmlewis/go-httpdebug v0.0.9/go.mod h1:t6xDKFIjenEc4rouOt79Oo6N09EiHFgMjbCOiQnOnOc=
7274
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
7375
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
7476
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -129,8 +131,8 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
129131
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
130132
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
131133
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
132-
github.com/mark3labs/mcp-go v0.23.1 h1:RzTzZ5kJ+HxwnutKA4rll8N/pKV6Wh5dhCmiJUu5S9I=
133-
github.com/mark3labs/mcp-go v0.23.1/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
134+
github.com/mark3labs/mcp-go v0.25.0 h1:UUpcMT3L5hIhuDy7aifj4Bphw4Pfx1Rf8mzMXDe8RQw=
135+
github.com/mark3labs/mcp-go v0.25.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
134136
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
135137
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
136138
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=

go.work.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDA
135135
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
136136
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
137137
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
138+
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
138139
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
139140
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
140141
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=

pkg/cmd/mcp/mcp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ func (o *ServerOptions) Complete() error {
8282
if o.Options.PulsarInstance != "" && o.Options.PulsarCluster != "" {
8383
err = mcp.SetContext(o.Options, o.Options.PulsarInstance, o.Options.PulsarCluster)
8484
if err != nil {
85+
mcp.ResetMcpContext()
8586
return errors.Wrap(err, "failed to set StreamNative Cloud context")
8687
}
8788
}
@@ -141,7 +142,7 @@ func (o *ServerOptions) Complete() error {
141142
TLSTrustCertsFilePath: snConfig.ExternalPulsar.TLSTrustCertsFilePath,
142143
TLSCertFile: snConfig.ExternalPulsar.TLSCertFile,
143144
TLSKeyFile: snConfig.ExternalPulsar.TLSKeyFile,
144-
})
145+
}, nil, nil)
145146
if err != nil {
146147
return errors.Wrap(err, "failed to set external Pulsar context")
147148
}

pkg/cmd/mcp/stdio.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ func newStdioServer(configOpts *ServerOptions, logrusLogger *logrus.Logger) *ser
143143

144144
mcp.RegisterPrompts(s)
145145
mcp.RegisterContextTools(s, configOpts.Features)
146+
mcp.StreamNativeAddLogTools(s, configOpts.ReadOnly, configOpts.Features)
146147
}
147148
case snConfig.ExternalKafka != nil:
148149
{

pkg/config/apiclient.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"golang.org/x/oauth2"
2828
"k8s.io/utils/clock"
2929

30+
dbg "github.com/gmlewis/go-httpdebug/httpdebug"
3031
"github.com/streamnative/streamnative-mcp-server/pkg/auth"
3132
"github.com/streamnative/streamnative-mcp-server/pkg/auth/cache"
3233
"github.com/streamnative/streamnative-mcp-server/pkg/auth/store"
@@ -35,6 +36,7 @@ import (
3536

3637
var SNCloudClientConfiguration *sncloud.Configuration
3738
var SNCloudClient *sncloud.APIClient
39+
var SNCloudLogClient *http.Client
3840

3941
// OAuth2TokenRefresher implements oauth2.TokenSource interface for refreshing OAuth2 tokens
4042
// This is now a wrapper around the cache.CachingTokenSource to leverage the existing token caching
@@ -183,3 +185,40 @@ func TokenRefreshed(audience string, token *oauth2.Token, tokenStore store.Store
183185
// Save back to store
184186
return tokenStore.SaveGrant(audience, *grant)
185187
}
188+
189+
func InitSNCloudLogClient(issuerData auth.Issuer, tokenStore store.Store) error {
190+
refresher, err := auth.NewDefaultClientCredentialsGrantRefresher(issuerData, clock.RealClock{})
191+
if err != nil {
192+
return errors.Wrap(err, "failed to create token refresher")
193+
}
194+
195+
tokenRefresher, err := NewOAuth2TokenRefresher(tokenStore, issuerData.Audience, refresher)
196+
if err != nil {
197+
return errors.Wrap(err, "failed to create token refresher")
198+
}
199+
200+
tokenSource := oauth2.ReuseTokenSource(nil, tokenRefresher)
201+
b := dbg.New()
202+
b.RedactEntireJWT = false
203+
SNCloudLogClient = &http.Client{
204+
Timeout: 10 * time.Second,
205+
Transport: &oauth2.Transport{
206+
Source: tokenSource,
207+
// Base: http.DefaultTransport,
208+
Base: b,
209+
},
210+
}
211+
212+
return nil
213+
}
214+
215+
func ResetSNCloudLogClient() {
216+
SNCloudLogClient = nil
217+
}
218+
219+
func GetSNCloudLogClient() (*http.Client, error) {
220+
if SNCloudLogClient == nil {
221+
return nil, errors.New("log tools are for StreamNative Cloud only, please check your context")
222+
}
223+
return SNCloudLogClient, nil
224+
}

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type SnConfig struct {
3636
// settable context
3737
Context Context `yaml:"context"`
3838
ProxyLocation string `yaml:"proxy-location"`
39+
LogLocation string `yaml:"log-location"`
3940
KeyFile string `yaml:"key-file"`
4041

4142
ExternalKafka *ExternalKafka `yaml:"external-kafka"`

pkg/config/options.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
GlobalDefaultAudience = "https://api.streamnative.cloud"
3535
GlobalDefaultAPIServer = "https://api.streamnative.cloud"
3636
GlobalDefaultProxyLocation = "https://proxy.streamnative.cloud"
37+
GlobalDefaultLogLocation = "https://log.streamnative.cloud"
3738
)
3839

3940
// Options represents the common options used throughout the program.
@@ -52,6 +53,7 @@ type Options struct {
5253
PulsarInstance string
5354
PulsarCluster string
5455
ProxyLocation string
56+
LogLocation string
5557
KeyFile string
5658

5759
UseExternalKafka bool
@@ -85,6 +87,8 @@ func (o *Options) AddFlags(cmd *cobra.Command) {
8587
"The organization to use for the API server")
8688
cmd.PersistentFlags().StringVar(&o.ProxyLocation, "proxy-location", GlobalDefaultProxyLocation,
8789
"The proxy location to use for the API server")
90+
cmd.PersistentFlags().StringVar(&o.LogLocation, "log-location", GlobalDefaultLogLocation,
91+
"The log location to use for the API server")
8892
_ = cmd.MarkFlagRequired("organization")
8993
cmd.PersistentFlags().StringVar(&o.PulsarInstance, "pulsar-instance", "",
9094
"The default instance to use for the API server")
@@ -192,6 +196,7 @@ func (o *Options) LoadConfig() (*SnConfig, error) {
192196
PulsarCluster: o.PulsarCluster,
193197
},
194198
ProxyLocation: o.ProxyLocation,
199+
LogLocation: o.LogLocation,
195200
KeyFile: o.KeyFile,
196201
}
197202
if o.UseExternalKafka {

pkg/kafka/connection.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ func NewCurrentKafkaContext(kc KafkaContext) error {
6565
return kc.SetKafkaContext()
6666
}
6767

68+
func ResetCurrentKafkaContext() {
69+
CurrentKafkaContext = KafkaContext{}
70+
KafkaAdminClient = nil
71+
KafkaClient = nil
72+
KafkaSchemaRegistryClient = nil
73+
KafkaConnectClient = nil
74+
}
75+
6876
type SASLConfig struct {
6977
Mechanism string
7078
Username string

pkg/mcp/context.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package mcp
19+
20+
var McpContextPulsarInstance *string
21+
var McpContextPulsarCluster *string
22+
var McpContextOrganization *string
23+
24+
func SetMcpContext(instance, cluster, organization string) {
25+
McpContextPulsarInstance = &instance
26+
McpContextPulsarCluster = &cluster
27+
McpContextOrganization = &organization
28+
}
29+
30+
func GetMcpContext() (string, string, string) {
31+
return *McpContextPulsarInstance, *McpContextPulsarCluster, *McpContextOrganization
32+
}
33+
34+
func ResetMcpContext() {
35+
McpContextPulsarInstance = nil
36+
McpContextPulsarCluster = nil
37+
McpContextOrganization = nil
38+
}

0 commit comments

Comments
 (0)