Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
42d8416
build(deps): bump golang.org/x/text from 0.36.0 to 0.37.0
dependabot[bot] May 15, 2026
f1d9949
build(deps): bump vue-router from 5.0.6 to 5.0.7 in /webui
dependabot[bot] May 15, 2026
6b9cbe3
Merge pull request #971 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] May 15, 2026
c64775a
build(deps-dev): bump @playwright/test from 1.59.1 to 1.60.0 in /webui
dependabot[bot] May 15, 2026
eb85550
Merge pull request #967 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] May 15, 2026
a0eacc3
build(deps-dev): bump eslint from 10.2.1 to 10.3.0 in /webui
dependabot[bot] May 15, 2026
d99ba31
Merge pull request #969 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] May 15, 2026
9b210b2
build(deps-dev): bump @vitejs/plugin-vue from 6.0.6 to 6.0.7 in /webui
dependabot[bot] May 15, 2026
fbbb3c7
Merge pull request #972 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] May 15, 2026
6b5f9b0
build(deps-dev): bump @types/node from 25.6.2 to 25.8.0 in /webui
dependabot[bot] May 15, 2026
4e75f16
Merge pull request #970 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] May 15, 2026
0acddc1
feat(search): add description to HTTP search results
marle3003 May 18, 2026
fb76326
wip(webui): improve display search results
marle3003 May 18, 2026
c27940d
Merge remote-tracking branch 'origin/develop' into develop
marle3003 May 18, 2026
a6eca56
refactor(validation): improve error message
marle3003 May 20, 2026
1a6c241
Merge branch 'develop' into dependabot/go_modules/develop/golang.org/…
marle3003 May 20, 2026
2d84682
Merge pull request #968 from marle3003/dependabot/go_modules/develop/…
github-actions[bot] May 20, 2026
26f9a1d
build(deps): bump golang.org/x/net from 0.53.0 to 0.54.0
dependabot[bot] May 20, 2026
162bc53
Merge pull request #966 from marle3003/dependabot/go_modules/develop/…
github-actions[bot] May 20, 2026
d3d0bf6
feat(search): add description to Kafka search result item
marle3003 May 20, 2026
50fda19
Merge remote-tracking branch 'origin/develop' into develop
marle3003 May 20, 2026
eb2c7a9
Merge branch 'main' into develop
marle3003 May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion acceptance/petstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (suite *PetStoreSuite) TestJsHttpHandler() {
try.GetRequest(suite.T(), "http://127.0.0.1:18080/pet/4",
map[string]string{"Accept": "application/json", "api_key": "123"},
try.HasStatusCode(http.StatusInternalServerError),
try.HasBody("encoding data to 'application/json' failed: error count 1:\n\t- #/required: required properties are missing: name, photoUrls\n"))
try.HasBody("HTTP body marshalling failed.\n\nBody: {}\n\nValidation error count 1:\n\t- #/required: required properties are missing: name, photoUrls\n"))

// use generated data but change pet's name
try.GetRequest(suite.T(), "http://127.0.0.1:18080/pet/5",
Expand Down
4 changes: 2 additions & 2 deletions api/handler_kafka_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
{
Partition: -1,
Offset: -1,
Error: "no matching message configuration found for the given value: 123\nhint:\nencoding data to 'application/json' failed: error count 1:\n\t- #/type: invalid type, expected string but got number\n",
Error: "Kafka message validation failed:\n\nMessage:\n123\n\nValidation error count 1:\n\t- #/type: invalid type, expected string but got number\n",
},
},
}, data)
Expand Down Expand Up @@ -929,7 +929,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
{
Partition: -1,
Offset: -1,
Error: "invalid message: error count 1:\n\t- #/additionalProperties: property 'yuh' not defined and the schema does not allow additional properties",
Error: "Validation error count 1:\n\t- #/additionalProperties: property 'yuh' not defined and the schema does not allow additional properties",
},
},
}, data)
Expand Down
2 changes: 1 addition & 1 deletion engine/kafka.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func selectMessage(value any, topic *asyncapi3.Channel, cfg *asyncapi3.Config) (
}
}
if validationErr != nil {
return nil, fmt.Errorf("no matching message configuration found for the given value: %v\nhint:\n%w\n", value, validationErr)
return nil, fmt.Errorf("Kafka message validation failed:\n\nMessage:\n%v\n\n%s\n", value, validationErr)
}
return nil, nil
}
Expand Down
6 changes: 3 additions & 3 deletions engine/kafka_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ func TestKafkaClient(t *testing.T) {
produce({ topic: 'foo', messages: [{ data: 12 }] })
}
`))
require.EqualError(t, err, "failed to produce message to Kafka topic 'foo': no matching message configuration found for the given value: 12\nhint:\nencoding data to 'application/json' failed: error count 1:\n\t- #/type: invalid type, expected string but got integer\n at mokapi/js/kafka.(*Module).Produce-fm (native)")
require.EqualError(t, err, "failed to produce message to Kafka topic 'foo': Kafka message validation failed:\n\nMessage:\n12\n\nValidation error count 1:\n\t- #/type: invalid type, expected string but got integer\n at mokapi/js/kafka.(*Module).Produce-fm (native)")

b, errCode := app.Kafka.Get("foo").Store.Topic("foo").Partition(0).Read(0, 1000)
require.Equal(t, kafka.None, errCode)
Expand All @@ -516,7 +516,7 @@ func TestKafkaClient(t *testing.T) {

// logs
require.Len(t, hook.Entries, 2)
require.Equal(t, "js error: failed to produce message to Kafka topic 'foo': no matching message configuration found for the given value: 12\nhint:\nencoding data to 'application/json' failed: error count 1:\n\t- #/type: invalid type, expected string but got integer\n in test.js", hook.LastEntry().Message)
require.Equal(t, "js error: failed to produce message to Kafka topic 'foo': Kafka message validation failed:\n\nMessage:\n12\n\nValidation error count 1:\n\t- #/type: invalid type, expected string but got integer\n in test.js", hook.LastEntry().Message)
},
},
{
Expand Down Expand Up @@ -734,7 +734,7 @@ func TestKafkaClient(t *testing.T) {
produce({ messages: [{ data: { foo: 'bar' } }] })
}
`))
require.EqualError(t, err, "failed to produce message to Kafka topic 'foo': no matching message configuration found for the given value: {\"foo\":\"bar\"}\nhint:\nencoding data to 'application/xml' failed: error count 1:\n\t- #/required: required properties are missing: id\n at mokapi/js/kafka.(*Module).Produce-fm (native)")
require.EqualError(t, err, "failed to produce message to Kafka topic 'foo': Kafka message validation failed:\n\nMessage:\n{\"foo\":\"bar\"}\n\nValidation error count 1:\n\t- #/required: required properties are missing: id\n at mokapi/js/kafka.(*Module).Produce-fm (native)")
},
},
{
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ require (
github.com/sirupsen/logrus v1.9.4
github.com/stretchr/testify v1.11.1
github.com/yuin/gopher-lua v1.1.2
golang.org/x/net v0.53.0
golang.org/x/text v0.36.0
golang.org/x/net v0.54.0
golang.org/x/text v0.37.0
gopkg.in/go-asn1-ber/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d
gopkg.in/yaml.v3 v3.0.1
layeh.com/gopher-luar v1.0.11
Expand Down Expand Up @@ -88,9 +88,9 @@ require (
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.etcd.io/bbolt v1.4.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.50.0 // indirect
golang.org/x/crypto v0.51.0 // indirect
golang.org/x/oauth2 v0.35.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/sys v0.44.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,13 @@ go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
Expand All @@ -224,17 +224,17 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
2 changes: 1 addition & 1 deletion js/mokapi/mokapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestModule(t *testing.T) {
const m = require('mokapi')
m.marshal('foo', { schema: {type: 'integer'}, contentType: 'application/json' })
`)
r.EqualError(t, err, "encoding data to 'application/json' failed: error count 1:\n\t- #/type: invalid type, expected integer but got string at mokapi/js/mokapi.(*Module).Marshal-fm (native)")
r.EqualError(t, err, "Validation error count 1:\n\t- #/type: invalid type, expected integer but got string at mokapi/js/mokapi.(*Module).Marshal-fm (native)")
},
},
{
Expand Down
23 changes: 22 additions & 1 deletion lib/type.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package lib

import "reflect"
import (
"encoding/json"
"fmt"
"reflect"

log "github.com/sirupsen/logrus"
)

func TypeFrom(v interface{}) string {
return TypeString(reflect.TypeOf(v))
Expand All @@ -26,3 +32,18 @@ func TypeString(t reflect.Type) string {
return "Unknown"
}
}

func PrettyPrint(v any) string {
if v == nil {
return "<nil>"
}
if s, ok := v.(string); ok {
return s
}
b, err := json.MarshalIndent(v, "", " ")
if err == nil {
return string(b)
}
log.Warnf("failed to pretty print %#v: %v", v, err)
return fmt.Sprintf("%v", v)
}
20 changes: 17 additions & 3 deletions mcp/data/automation-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface Mokapi {
* @example
* getApi('Swagger Petstore')
*/
getApi(name: string): OpenApi | Kafka;
getApi(name: string): Http | Kafka;

/**
* Generate a random value from a JSON Schema.
Expand Down Expand Up @@ -54,8 +54,20 @@ interface Mokapi {
getEvent(id: string): Event[];

/**
* Advanced Search across all APIs, Topics, and Documentation.
* By default, multiple terms are combined with OR (results contain at least one term). Use prefixes to enforce stricter matches.
* Advanced search across all APIs, topics, documentation, events and logs.
*
* Search behavior:
* - Multiple search terms are combined with OR by default
* Example: "pet booking"
* → matches results containing either "pet" OR "booking"
*
* Prefix a term with '+' to require that term to match.
* Example: "+pet booking"
* → matches results containing "pet" AND optionally "booking"
*
* Multiple '+' terms are combined with AND.
* Example: "+pet +booking"
* → matches results containing both "pet" AND "booking"
*
* QUERY SYNTAX:
* - Simple: `petstore` (Search in all fields)
Expand Down Expand Up @@ -94,6 +106,8 @@ interface SearchResultItem {
domain: string
/** A human-readable title or summary */
title: string
/** A human-readable description */
description: string
/**
* Relevant text snippets showing where the match was found.
* Useful to see context like 'GET /pets' or 'Topic: orders'.
Expand Down
4 changes: 4 additions & 0 deletions mcp/data/automation-kafka.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ interface KafkaMessage {
summary: string
description: string
contentType: string
/**
* JSON schema describing the Kafka message payload.
* Use fake(payload) to generate valid example data.
*/
payload: Schema;
key: Schema
headers?: Schema;
Expand Down
26 changes: 14 additions & 12 deletions mcp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,13 @@ type SearchResult struct {
}

type SearchResultItem struct {
Type string `json:"type"`
Domain string `json:"domain,omitempty"`
Title string `json:"title"`
Fragments []string `json:"fragments,omitempty"`
Metadata map[string]string `json:"metadata"`
Time string `json:"time,omitempty"`
Type string `json:"type"`
Domain string `json:"domain,omitempty"`
Title string `json:"title"`
Description string `json:"description"`
Fragments []string `json:"fragments,omitempty"`
Metadata map[string]string `json:"metadata"`
Time string `json:"time,omitempty"`
}

func (m *mokapi) search(queryText string, index int, limit int) (SearchResult, error) {
Expand All @@ -220,12 +221,13 @@ func (m *mokapi) search(queryText string, index int, limit int) (SearchResult, e
}
for _, item := range sr.Results {
result.Items = append(result.Items, SearchResultItem{
Type: item.Type,
Domain: item.Domain,
Title: item.Title,
Fragments: item.Fragments,
Metadata: item.Params,
Time: item.Time,
Type: item.Type,
Domain: item.Domain,
Title: item.Title,
Description: item.Description,
Fragments: item.Fragments,
Metadata: item.Params,
Time: item.Time,
})
}
return result, nil
Expand Down
51 changes: 32 additions & 19 deletions mcp/run_kafka.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package mcp

import (
"errors"
"fmt"
"mokapi/kafka"
"mokapi/media"
"mokapi/providers/asyncapi3"
"mokapi/providers/asyncapi3/kafka/store"
"mokapi/runtime"
"slices"
Expand Down Expand Up @@ -165,25 +165,20 @@ func (k *Kafka) GetTopic(name string) (Topic, error) {
Description: op.Value.Description,
}

for _, msg := range op.Value.Messages {
if msg.Value == nil {
continue
}
m := KafkaMessage{
Name: msg.Value.Name,
Title: msg.Value.Title,
Summary: msg.Value.Summary,
Description: msg.Value.Description,
ContentType: msg.Value.ContentType,
Headers: msg.Value.Headers,
}
if msg.Value.Payload != nil {
m.Payload = msg.Value.Payload.Value
if len(op.Value.Messages) > 0 {
for _, msg := range op.Value.Messages {
if msg.Value == nil {
continue
}
result.Messages = append(result.Messages, getKafkaMessages(msg))
}
if msg.Value.Bindings.Kafka.Key != nil {
m.Key = msg.Value.Bindings.Kafka.Key
} else {
for _, msg := range ch.Value.Messages {
if msg.Value == nil {
continue
}
result.Messages = append(result.Messages, getKafkaMessages(msg))
}
result.Messages = append(result.Messages, m)
}

t.Operations = append(t.Operations, result)
Expand Down Expand Up @@ -220,7 +215,7 @@ func (t *Topic) Produce(partition int, value any, key string, headers map[string
}

if len(result) > 0 && result[0].Error != "" {
return errors.New(result[0].Error)
return fmt.Errorf("%s\nTo create a valid payload:\n1. Select a message from operation.messages\n2. Generate example data:\n\n const value = mokapi.fake(message.payload)\n\n3. Modify only the required fields if needed.", result[0].Error)
}

// update JS topic and partition
Expand Down Expand Up @@ -289,3 +284,21 @@ func (t *Topic) Consume(partition int, startOffset int64, limit int) ([]KafkaRec
}
}
}

func getKafkaMessages(msg *asyncapi3.MessageRef) KafkaMessage {
m := KafkaMessage{
Name: msg.Value.Name,
Title: msg.Value.Title,
Summary: msg.Value.Summary,
Description: msg.Value.Description,
ContentType: msg.Value.ContentType,
Headers: msg.Value.Headers,
}
if msg.Value.Payload != nil {
m.Payload = msg.Value.Payload.Value
}
if msg.Value.Bindings.Kafka.Key != nil {
m.Key = msg.Value.Bindings.Kafka.Key
}
return m
}
Loading
Loading